diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-17 11:07:59 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-17 11:46:13 -0500 |
commit | 36c9db7a1aca3396b26004a3c41f27e2b735536f (patch) | |
tree | 107c2e90b3d3a13f4582ecb0ac42fa1a98d2859e | |
parent | 8f0fdc09aacbf5df5ddeeb8768625ae9c52fab0f (diff) |
ALSA: hda - Use generic parser for STAC/IDT codec driver
Finally we reached here. All codecs driver (except for CA0132, which
has really device-specific requirements) have been converted to use
the generic parser.
This patch appears bigger than others since it also involves with the
code shuffling, but mostly the cut-off of parser codes and adapt to
the generic parser flags. Most of fixup codecs haven't been changed
but just removed a few unnecessary codes.
The only missing stuff is the SPDIF mux control. It'll be added again
later.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 4719 |
2 files changed, 769 insertions, 3951 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 4004d405e082..4466bf63d6bf 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -112,6 +112,7 @@ config SND_HDA_CODEC_ANALOG | |||
112 | config SND_HDA_CODEC_SIGMATEL | 112 | config SND_HDA_CODEC_SIGMATEL |
113 | bool "Build IDT/Sigmatel HD-audio codec support" | 113 | bool "Build IDT/Sigmatel HD-audio codec support" |
114 | default y | 114 | default y |
115 | select SND_HDA_GENERIC | ||
115 | help | 116 | help |
116 | Say Y here to include IDT (Sigmatel) HD-audio codec support in | 117 | Say Y here to include IDT (Sigmatel) HD-audio codec support in |
117 | snd-hda-intel driver, such as STAC9200. | 118 | snd-hda-intel driver, such as STAC9200. |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f9757356a1fe..9d2dfad7f0bc 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -39,14 +39,11 @@ | |||
39 | #include "hda_auto_parser.h" | 39 | #include "hda_auto_parser.h" |
40 | #include "hda_beep.h" | 40 | #include "hda_beep.h" |
41 | #include "hda_jack.h" | 41 | #include "hda_jack.h" |
42 | #include "hda_generic.h" | ||
42 | 43 | ||
43 | enum { | 44 | enum { |
44 | STAC_VREF_EVENT = 1, | 45 | STAC_VREF_EVENT = 8, |
45 | STAC_INSERT_EVENT, | ||
46 | STAC_PWR_EVENT, | 46 | STAC_PWR_EVENT, |
47 | STAC_HP_EVENT, | ||
48 | STAC_LO_EVENT, | ||
49 | STAC_MIC_EVENT, | ||
50 | }; | 47 | }; |
51 | 48 | ||
52 | enum { | 49 | enum { |
@@ -115,7 +112,6 @@ enum { | |||
115 | STAC_HP_DV4, | 112 | STAC_HP_DV4, |
116 | STAC_HP_DV5, | 113 | STAC_HP_DV5, |
117 | STAC_HP_HDX, | 114 | STAC_HP_HDX, |
118 | STAC_HP_DV4_1222NR, | ||
119 | STAC_92HD71BXX_HP, | 115 | STAC_92HD71BXX_HP, |
120 | STAC_92HD71BXX_NO_DMIC, | 116 | STAC_92HD71BXX_NO_DMIC, |
121 | STAC_92HD71BXX_NO_SMUX, | 117 | STAC_92HD71BXX_NO_SMUX, |
@@ -173,30 +169,14 @@ enum { | |||
173 | STAC_9872_MODELS | 169 | STAC_9872_MODELS |
174 | }; | 170 | }; |
175 | 171 | ||
176 | struct sigmatel_mic_route { | ||
177 | hda_nid_t pin; | ||
178 | signed char mux_idx; | ||
179 | signed char dmux_idx; | ||
180 | }; | ||
181 | |||
182 | #define MAX_PINS_NUM 16 | ||
183 | #define MAX_ADCS_NUM 4 | ||
184 | #define MAX_DMICS_NUM 4 | ||
185 | |||
186 | struct sigmatel_spec { | 172 | struct sigmatel_spec { |
187 | struct snd_kcontrol_new *mixers[4]; | 173 | struct hda_gen_spec gen; |
188 | unsigned int num_mixers; | ||
189 | 174 | ||
190 | unsigned int eapd_switch: 1; | 175 | unsigned int eapd_switch: 1; |
191 | unsigned int surr_switch: 1; | ||
192 | unsigned int alt_switch: 1; | ||
193 | unsigned int hp_detect: 1; | ||
194 | unsigned int spdif_mute: 1; | ||
195 | unsigned int check_volume_offset:1; | ||
196 | unsigned int auto_mic:1; | ||
197 | unsigned int linear_tone_beep:1; | 176 | unsigned int linear_tone_beep:1; |
198 | unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */ | 177 | unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */ |
199 | unsigned int volknob_init:1; /* special volume-knob initialization */ | 178 | unsigned int volknob_init:1; /* special volume-knob initialization */ |
179 | unsigned int powerdown_adcs:1; | ||
200 | 180 | ||
201 | /* gpio lines */ | 181 | /* gpio lines */ |
202 | unsigned int eapd_mask; | 182 | unsigned int eapd_mask; |
@@ -218,6 +198,7 @@ struct sigmatel_spec { | |||
218 | 198 | ||
219 | /* analog loopback */ | 199 | /* analog loopback */ |
220 | const struct snd_kcontrol_new *aloopback_ctl; | 200 | const struct snd_kcontrol_new *aloopback_ctl; |
201 | unsigned int aloopback; | ||
221 | unsigned char aloopback_mask; | 202 | unsigned char aloopback_mask; |
222 | unsigned char aloopback_shift; | 203 | unsigned char aloopback_shift; |
223 | 204 | ||
@@ -225,458 +206,130 @@ struct sigmatel_spec { | |||
225 | unsigned int power_map_bits; | 206 | unsigned int power_map_bits; |
226 | unsigned int num_pwrs; | 207 | unsigned int num_pwrs; |
227 | const hda_nid_t *pwr_nids; | 208 | const hda_nid_t *pwr_nids; |
228 | const hda_nid_t *dac_list; | 209 | unsigned int active_adcs; |
229 | 210 | ||
230 | /* playback */ | 211 | /* beep widgets */ |
231 | struct hda_input_mux *mono_mux; | ||
232 | unsigned int cur_mmux; | ||
233 | struct hda_multi_out multiout; | ||
234 | hda_nid_t dac_nids[5]; | ||
235 | hda_nid_t hp_dacs[5]; | ||
236 | hda_nid_t speaker_dacs[5]; | ||
237 | |||
238 | int volume_offset; | ||
239 | |||
240 | /* capture */ | ||
241 | const hda_nid_t *adc_nids; | ||
242 | unsigned int num_adcs; | ||
243 | const hda_nid_t *mux_nids; | ||
244 | unsigned int num_muxes; | ||
245 | const hda_nid_t *dmic_nids; | ||
246 | unsigned int num_dmics; | ||
247 | const hda_nid_t *dmux_nids; | ||
248 | unsigned int num_dmuxes; | ||
249 | const hda_nid_t *smux_nids; | ||
250 | unsigned int num_smuxes; | ||
251 | unsigned int num_analog_muxes; | ||
252 | |||
253 | const unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */ | ||
254 | const unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */ | ||
255 | unsigned int num_caps; /* number of capture volume/switch elements */ | ||
256 | |||
257 | struct sigmatel_mic_route ext_mic; | ||
258 | struct sigmatel_mic_route int_mic; | ||
259 | struct sigmatel_mic_route dock_mic; | ||
260 | |||
261 | const char * const *spdif_labels; | ||
262 | |||
263 | hda_nid_t dig_in_nid; | ||
264 | hda_nid_t mono_nid; | ||
265 | hda_nid_t anabeep_nid; | 212 | hda_nid_t anabeep_nid; |
266 | hda_nid_t digbeep_nid; | 213 | hda_nid_t digbeep_nid; |
267 | |||
268 | /* pin widgets */ | ||
269 | const hda_nid_t *pin_nids; | ||
270 | unsigned int num_pins; | ||
271 | |||
272 | /* codec specific stuff */ | ||
273 | const struct hda_verb *init; | ||
274 | const struct snd_kcontrol_new *mixer; | ||
275 | |||
276 | /* capture source */ | ||
277 | struct hda_input_mux *dinput_mux; | ||
278 | unsigned int cur_dmux[2]; | ||
279 | struct hda_input_mux *input_mux; | ||
280 | unsigned int cur_mux[3]; | ||
281 | struct hda_input_mux *sinput_mux; | ||
282 | unsigned int cur_smux[2]; | ||
283 | unsigned int cur_amux; | ||
284 | hda_nid_t *amp_nids; | ||
285 | unsigned int powerdown_adcs; | ||
286 | |||
287 | /* i/o switches */ | ||
288 | unsigned int io_switch[2]; | ||
289 | unsigned int clfe_swap; | ||
290 | hda_nid_t line_switch; /* shared line-in for input and output */ | ||
291 | hda_nid_t mic_switch; /* shared mic-in for input and output */ | ||
292 | hda_nid_t hp_switch; /* NID of HP as line-out */ | ||
293 | unsigned int aloopback; | ||
294 | |||
295 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
296 | |||
297 | /* dynamic controls and input_mux */ | ||
298 | struct auto_pin_cfg autocfg; | ||
299 | struct snd_array kctls; | ||
300 | struct hda_input_mux private_dimux; | ||
301 | struct hda_input_mux private_imux; | ||
302 | struct hda_input_mux private_smux; | ||
303 | struct hda_input_mux private_mono_mux; | ||
304 | |||
305 | /* auto spec */ | ||
306 | unsigned auto_pin_cnt; | ||
307 | hda_nid_t auto_pin_nids[MAX_PINS_NUM]; | ||
308 | unsigned auto_adc_cnt; | ||
309 | hda_nid_t auto_adc_nids[MAX_ADCS_NUM]; | ||
310 | hda_nid_t auto_mux_nids[MAX_ADCS_NUM]; | ||
311 | hda_nid_t auto_dmux_nids[MAX_ADCS_NUM]; | ||
312 | unsigned long auto_capvols[MAX_ADCS_NUM]; | ||
313 | unsigned auto_dmic_cnt; | ||
314 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; | ||
315 | |||
316 | struct hda_vmaster_mute_hook vmaster_mute; | ||
317 | }; | 214 | }; |
318 | 215 | ||
319 | #define AC_VERB_IDT_SET_POWER_MAP 0x7ec | 216 | #define AC_VERB_IDT_SET_POWER_MAP 0x7ec |
320 | #define AC_VERB_IDT_GET_POWER_MAP 0xfec | 217 | #define AC_VERB_IDT_GET_POWER_MAP 0xfec |
321 | 218 | ||
322 | static const hda_nid_t stac9200_adc_nids[1] = { | ||
323 | 0x03, | ||
324 | }; | ||
325 | |||
326 | static const hda_nid_t stac9200_mux_nids[1] = { | ||
327 | 0x0c, | ||
328 | }; | ||
329 | |||
330 | static const hda_nid_t stac9200_dac_nids[1] = { | ||
331 | 0x02, | ||
332 | }; | ||
333 | |||
334 | static const hda_nid_t stac92hd73xx_pwr_nids[8] = { | 219 | static const hda_nid_t stac92hd73xx_pwr_nids[8] = { |
335 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | 220 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, |
336 | 0x0f, 0x10, 0x11 | 221 | 0x0f, 0x10, 0x11 |
337 | }; | 222 | }; |
338 | 223 | ||
339 | static const hda_nid_t stac92hd73xx_slave_dig_outs[2] = { | ||
340 | 0x26, 0, | ||
341 | }; | ||
342 | |||
343 | static const hda_nid_t stac92hd73xx_adc_nids[2] = { | ||
344 | 0x1a, 0x1b | ||
345 | }; | ||
346 | |||
347 | #define STAC92HD73XX_NUM_DMICS 2 | ||
348 | static const hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { | ||
349 | 0x13, 0x14, 0 | ||
350 | }; | ||
351 | |||
352 | #define STAC92HD73_DAC_COUNT 5 | ||
353 | |||
354 | static const hda_nid_t stac92hd73xx_mux_nids[2] = { | ||
355 | 0x20, 0x21, | ||
356 | }; | ||
357 | |||
358 | static const hda_nid_t stac92hd73xx_dmux_nids[2] = { | ||
359 | 0x20, 0x21, | ||
360 | }; | ||
361 | |||
362 | static const hda_nid_t stac92hd73xx_smux_nids[2] = { | ||
363 | 0x22, 0x23, | ||
364 | }; | ||
365 | |||
366 | #define STAC92HD73XX_NUM_CAPS 2 | ||
367 | static const unsigned long stac92hd73xx_capvols[] = { | ||
368 | HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT), | ||
369 | HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), | ||
370 | }; | ||
371 | #define stac92hd73xx_capsws stac92hd73xx_capvols | ||
372 | |||
373 | #define STAC92HD83_DAC_COUNT 3 | ||
374 | |||
375 | static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { | 224 | static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { |
376 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | 225 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, |
377 | 0x0f, 0x10 | 226 | 0x0f, 0x10 |
378 | }; | 227 | }; |
379 | 228 | ||
380 | static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = { | ||
381 | 0x1e, 0, | ||
382 | }; | ||
383 | |||
384 | static const hda_nid_t stac92hd83xxx_dmic_nids[] = { | ||
385 | 0x11, 0x20, | ||
386 | }; | ||
387 | |||
388 | static const hda_nid_t stac92hd71bxx_pwr_nids[3] = { | 229 | static const hda_nid_t stac92hd71bxx_pwr_nids[3] = { |
389 | 0x0a, 0x0d, 0x0f | 230 | 0x0a, 0x0d, 0x0f |
390 | }; | 231 | }; |
391 | 232 | ||
392 | static const hda_nid_t stac92hd71bxx_adc_nids[2] = { | ||
393 | 0x12, 0x13, | ||
394 | }; | ||
395 | |||
396 | static const hda_nid_t stac92hd71bxx_mux_nids[2] = { | ||
397 | 0x1a, 0x1b | ||
398 | }; | ||
399 | |||
400 | static const hda_nid_t stac92hd71bxx_dmux_nids[2] = { | ||
401 | 0x1c, 0x1d, | ||
402 | }; | ||
403 | |||
404 | static const hda_nid_t stac92hd71bxx_smux_nids[2] = { | ||
405 | 0x24, 0x25, | ||
406 | }; | ||
407 | |||
408 | #define STAC92HD71BXX_NUM_DMICS 2 | ||
409 | static const hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { | ||
410 | 0x18, 0x19, 0 | ||
411 | }; | ||
412 | |||
413 | static const hda_nid_t stac92hd71bxx_dmic_5port_nids[STAC92HD71BXX_NUM_DMICS] = { | ||
414 | 0x18, 0 | ||
415 | }; | ||
416 | |||
417 | static const hda_nid_t stac92hd71bxx_slave_dig_outs[2] = { | ||
418 | 0x22, 0 | ||
419 | }; | ||
420 | |||
421 | #define STAC92HD71BXX_NUM_CAPS 2 | ||
422 | static const unsigned long stac92hd71bxx_capvols[] = { | ||
423 | HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), | ||
424 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
425 | }; | ||
426 | #define stac92hd71bxx_capsws stac92hd71bxx_capvols | ||
427 | |||
428 | static const hda_nid_t stac925x_adc_nids[1] = { | ||
429 | 0x03, | ||
430 | }; | ||
431 | |||
432 | static const hda_nid_t stac925x_mux_nids[1] = { | ||
433 | 0x0f, | ||
434 | }; | ||
435 | |||
436 | static const hda_nid_t stac925x_dac_nids[1] = { | ||
437 | 0x02, | ||
438 | }; | ||
439 | |||
440 | #define STAC925X_NUM_DMICS 1 | ||
441 | static const hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { | ||
442 | 0x15, 0 | ||
443 | }; | ||
444 | |||
445 | static const hda_nid_t stac925x_dmux_nids[1] = { | ||
446 | 0x14, | ||
447 | }; | ||
448 | |||
449 | static const unsigned long stac925x_capvols[] = { | ||
450 | HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT), | ||
451 | }; | ||
452 | static const unsigned long stac925x_capsws[] = { | ||
453 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
454 | }; | ||
455 | |||
456 | static const hda_nid_t stac922x_adc_nids[2] = { | ||
457 | 0x06, 0x07, | ||
458 | }; | ||
459 | |||
460 | static const hda_nid_t stac922x_mux_nids[2] = { | ||
461 | 0x12, 0x13, | ||
462 | }; | ||
463 | 233 | ||
464 | #define STAC922X_NUM_CAPS 2 | 234 | /* |
465 | static const unsigned long stac922x_capvols[] = { | 235 | * PCM hooks |
466 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT), | 236 | */ |
467 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), | 237 | static void stac_playback_pcm_hook(struct hda_pcm_stream *hinfo, |
468 | }; | 238 | struct hda_codec *codec, |
469 | #define stac922x_capsws stac922x_capvols | 239 | struct snd_pcm_substream *substream, |
470 | 240 | int action) | |
471 | static const hda_nid_t stac927x_slave_dig_outs[2] = { | ||
472 | 0x1f, 0, | ||
473 | }; | ||
474 | |||
475 | static const hda_nid_t stac927x_adc_nids[3] = { | ||
476 | 0x07, 0x08, 0x09 | ||
477 | }; | ||
478 | |||
479 | static const hda_nid_t stac927x_mux_nids[3] = { | ||
480 | 0x15, 0x16, 0x17 | ||
481 | }; | ||
482 | |||
483 | static const hda_nid_t stac927x_smux_nids[1] = { | ||
484 | 0x21, | ||
485 | }; | ||
486 | |||
487 | static const hda_nid_t stac927x_dac_nids[6] = { | ||
488 | 0x02, 0x03, 0x04, 0x05, 0x06, 0 | ||
489 | }; | ||
490 | |||
491 | static const hda_nid_t stac927x_dmux_nids[1] = { | ||
492 | 0x1b, | ||
493 | }; | ||
494 | |||
495 | #define STAC927X_NUM_DMICS 2 | ||
496 | static const hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = { | ||
497 | 0x13, 0x14, 0 | ||
498 | }; | ||
499 | |||
500 | #define STAC927X_NUM_CAPS 3 | ||
501 | static const unsigned long stac927x_capvols[] = { | ||
502 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), | ||
503 | HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT), | ||
504 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT), | ||
505 | }; | ||
506 | static const unsigned long stac927x_capsws[] = { | ||
507 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
508 | HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), | ||
509 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
510 | }; | ||
511 | |||
512 | static const char * const stac927x_spdif_labels[5] = { | ||
513 | "Digital Playback", "ADAT", "Analog Mux 1", | ||
514 | "Analog Mux 2", "Analog Mux 3" | ||
515 | }; | ||
516 | |||
517 | static const hda_nid_t stac9205_adc_nids[2] = { | ||
518 | 0x12, 0x13 | ||
519 | }; | ||
520 | |||
521 | static const hda_nid_t stac9205_mux_nids[2] = { | ||
522 | 0x19, 0x1a | ||
523 | }; | ||
524 | |||
525 | static const hda_nid_t stac9205_dmux_nids[1] = { | ||
526 | 0x1d, | ||
527 | }; | ||
528 | |||
529 | static const hda_nid_t stac9205_smux_nids[1] = { | ||
530 | 0x21, | ||
531 | }; | ||
532 | |||
533 | #define STAC9205_NUM_DMICS 2 | ||
534 | static const hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { | ||
535 | 0x17, 0x18, 0 | ||
536 | }; | ||
537 | |||
538 | #define STAC9205_NUM_CAPS 2 | ||
539 | static const unsigned long stac9205_capvols[] = { | ||
540 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT), | ||
541 | HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT), | ||
542 | }; | ||
543 | static const unsigned long stac9205_capsws[] = { | ||
544 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
545 | HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT), | ||
546 | }; | ||
547 | |||
548 | static const hda_nid_t stac9200_pin_nids[8] = { | ||
549 | 0x08, 0x09, 0x0d, 0x0e, | ||
550 | 0x0f, 0x10, 0x11, 0x12, | ||
551 | }; | ||
552 | |||
553 | static const hda_nid_t stac925x_pin_nids[8] = { | ||
554 | 0x07, 0x08, 0x0a, 0x0b, | ||
555 | 0x0c, 0x0d, 0x10, 0x11, | ||
556 | }; | ||
557 | |||
558 | static const hda_nid_t stac922x_pin_nids[10] = { | ||
559 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
560 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | ||
561 | }; | ||
562 | |||
563 | static const hda_nid_t stac92hd73xx_pin_nids[13] = { | ||
564 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
565 | 0x0f, 0x10, 0x11, 0x12, 0x13, | ||
566 | 0x14, 0x22, 0x23 | ||
567 | }; | ||
568 | |||
569 | #define STAC92HD71BXX_NUM_PINS 13 | ||
570 | static const hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { | ||
571 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, | ||
572 | 0x00, 0x14, 0x18, 0x19, 0x1e, | ||
573 | 0x1f, 0x20, 0x27 | ||
574 | }; | ||
575 | static const hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = { | ||
576 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
577 | 0x0f, 0x14, 0x18, 0x19, 0x1e, | ||
578 | 0x1f, 0x20, 0x27 | ||
579 | }; | ||
580 | |||
581 | static const hda_nid_t stac927x_pin_nids[14] = { | ||
582 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
583 | 0x0f, 0x10, 0x11, 0x12, 0x13, | ||
584 | 0x14, 0x21, 0x22, 0x23, | ||
585 | }; | ||
586 | |||
587 | static const hda_nid_t stac9205_pin_nids[12] = { | ||
588 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
589 | 0x0f, 0x14, 0x16, 0x17, 0x18, | ||
590 | 0x21, 0x22, | ||
591 | }; | ||
592 | |||
593 | static int stac_add_event(struct hda_codec *codec, hda_nid_t nid, | ||
594 | unsigned char type, int data); | ||
595 | static int stac_add_hp_bass_switch(struct hda_codec *codec); | ||
596 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, | ||
597 | hda_nid_t nid, int pin_type); | ||
598 | static int hp_bnb2011_with_dock(struct hda_codec *codec); | ||
599 | static int hp_blike_system(u32 subsystem_id); | ||
600 | static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity); | ||
601 | |||
602 | static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, | ||
603 | struct snd_ctl_elem_info *uinfo) | ||
604 | { | 241 | { |
605 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
606 | struct sigmatel_spec *spec = codec->spec; | 242 | struct sigmatel_spec *spec = codec->spec; |
607 | return snd_hda_input_mux_info(spec->dinput_mux, uinfo); | 243 | if (action == HDA_GEN_PCM_ACT_OPEN && spec->stream_delay) |
244 | msleep(spec->stream_delay); | ||
608 | } | 245 | } |
609 | 246 | ||
610 | static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol, | 247 | static void stac_capture_pcm_hook(struct hda_pcm_stream *hinfo, |
611 | struct snd_ctl_elem_value *ucontrol) | 248 | struct hda_codec *codec, |
249 | struct snd_pcm_substream *substream, | ||
250 | int action) | ||
612 | { | 251 | { |
613 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
614 | struct sigmatel_spec *spec = codec->spec; | 252 | struct sigmatel_spec *spec = codec->spec; |
615 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 253 | int i, idx = 0; |
616 | 254 | ||
617 | ucontrol->value.enumerated.item[0] = spec->cur_dmux[dmux_idx]; | 255 | if (!spec->powerdown_adcs) |
618 | return 0; | 256 | return; |
619 | } | ||
620 | 257 | ||
621 | static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, | 258 | for (i = 0; i < spec->gen.num_all_adcs; i++) { |
622 | struct snd_ctl_elem_value *ucontrol) | 259 | if (spec->gen.all_adcs[i] == hinfo->nid) { |
623 | { | 260 | idx = i; |
624 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 261 | break; |
625 | struct sigmatel_spec *spec = codec->spec; | 262 | } |
626 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 263 | } |
627 | 264 | ||
628 | return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, | 265 | switch (action) { |
629 | spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); | 266 | case HDA_GEN_PCM_ACT_OPEN: |
267 | msleep(40); | ||
268 | snd_hda_codec_write(codec, hinfo->nid, 0, | ||
269 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
270 | spec->active_adcs |= (1 << idx); | ||
271 | break; | ||
272 | case HDA_GEN_PCM_ACT_CLOSE: | ||
273 | snd_hda_codec_write(codec, hinfo->nid, 0, | ||
274 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
275 | spec->active_adcs &= ~(1 << idx); | ||
276 | break; | ||
277 | } | ||
630 | } | 278 | } |
631 | 279 | ||
632 | static int stac92xx_smux_enum_info(struct snd_kcontrol *kcontrol, | 280 | /* |
633 | struct snd_ctl_elem_info *uinfo) | 281 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a |
634 | { | 282 | * funky external mute control using GPIO pins. |
635 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 283 | */ |
636 | struct sigmatel_spec *spec = codec->spec; | ||
637 | return snd_hda_input_mux_info(spec->sinput_mux, uinfo); | ||
638 | } | ||
639 | 284 | ||
640 | static int stac92xx_smux_enum_get(struct snd_kcontrol *kcontrol, | 285 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, |
641 | struct snd_ctl_elem_value *ucontrol) | 286 | unsigned int dir_mask, unsigned int data) |
642 | { | 287 | { |
643 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 288 | unsigned int gpiostate, gpiomask, gpiodir; |
644 | struct sigmatel_spec *spec = codec->spec; | ||
645 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
646 | 289 | ||
647 | ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; | 290 | snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); |
648 | return 0; | 291 | |
292 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | ||
293 | AC_VERB_GET_GPIO_DATA, 0); | ||
294 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | ||
295 | |||
296 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | ||
297 | AC_VERB_GET_GPIO_MASK, 0); | ||
298 | gpiomask |= mask; | ||
299 | |||
300 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | ||
301 | AC_VERB_GET_GPIO_DIRECTION, 0); | ||
302 | gpiodir |= dir_mask; | ||
303 | |||
304 | /* Configure GPIOx as CMOS */ | ||
305 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | ||
306 | |||
307 | snd_hda_codec_write(codec, codec->afg, 0, | ||
308 | AC_VERB_SET_GPIO_MASK, gpiomask); | ||
309 | snd_hda_codec_read(codec, codec->afg, 0, | ||
310 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ | ||
311 | |||
312 | msleep(1); | ||
313 | |||
314 | snd_hda_codec_read(codec, codec->afg, 0, | ||
315 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | ||
649 | } | 316 | } |
650 | 317 | ||
651 | static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | 318 | /* hook for controlling mic-mute LED GPIO */ |
652 | struct snd_ctl_elem_value *ucontrol) | 319 | static void stac_capture_led_hook(struct hda_codec *codec, bool enable) |
653 | { | 320 | { |
654 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
655 | struct sigmatel_spec *spec = codec->spec; | 321 | struct sigmatel_spec *spec = codec->spec; |
656 | struct hda_input_mux *smux = &spec->private_smux; | 322 | bool mute = !enable; |
657 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
658 | int err, val; | ||
659 | hda_nid_t nid; | ||
660 | |||
661 | err = snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, | ||
662 | spec->smux_nids[smux_idx], &spec->cur_smux[smux_idx]); | ||
663 | if (err < 0) | ||
664 | return err; | ||
665 | 323 | ||
666 | if (spec->spdif_mute) { | 324 | if (spec->mic_mute_led_on != mute) { |
667 | if (smux_idx == 0) | 325 | spec->mic_mute_led_on = mute; |
668 | nid = spec->multiout.dig_out_nid; | 326 | if (mute) |
669 | else | 327 | spec->gpio_data |= spec->mic_mute_led_gpio; |
670 | nid = codec->slave_dig_outs[smux_idx - 1]; | ||
671 | if (spec->cur_smux[smux_idx] == smux->num_items - 1) | ||
672 | val = HDA_AMP_MUTE; | ||
673 | else | 328 | else |
674 | val = 0; | 329 | spec->gpio_data &= ~spec->mic_mute_led_gpio; |
675 | /* un/mute SPDIF out */ | 330 | stac_gpio_set(codec, spec->gpio_mask, |
676 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | 331 | spec->gpio_dir, spec->gpio_data); |
677 | HDA_AMP_MUTE, val); | ||
678 | } | 332 | } |
679 | return 0; | ||
680 | } | 333 | } |
681 | 334 | ||
682 | static int stac_vrefout_set(struct hda_codec *codec, | 335 | static int stac_vrefout_set(struct hda_codec *codec, |
@@ -702,129 +355,221 @@ static int stac_vrefout_set(struct hda_codec *codec, | |||
702 | return 1; | 355 | return 1; |
703 | } | 356 | } |
704 | 357 | ||
705 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, | 358 | /* update mute-LED accoring to the master switch */ |
706 | hda_nid_t nid, unsigned int new_vref) | 359 | static void stac_update_led_status(struct hda_codec *codec, int enabled) |
707 | { | 360 | { |
708 | int error; | 361 | struct sigmatel_spec *spec = codec->spec; |
709 | unsigned int pincfg; | 362 | int muted = !enabled; |
710 | pincfg = snd_hda_codec_read(codec, nid, 0, | ||
711 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
712 | 363 | ||
713 | pincfg &= 0xff; | 364 | if (!spec->gpio_led) |
714 | pincfg &= ~(AC_PINCTL_VREFEN | AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 365 | return; |
715 | pincfg |= new_vref; | ||
716 | 366 | ||
717 | if (new_vref == AC_PINCTL_VREF_HIZ) | 367 | /* LED state is inverted on these systems */ |
718 | pincfg |= AC_PINCTL_OUT_EN; | 368 | if (spec->gpio_led_polarity) |
719 | else | 369 | muted = !muted; |
720 | pincfg |= AC_PINCTL_IN_EN; | ||
721 | 370 | ||
722 | error = snd_hda_set_pin_ctl_cache(codec, nid, pincfg); | 371 | if (!spec->vref_mute_led_nid) { |
723 | if (error < 0) | 372 | if (muted) |
724 | return error; | 373 | spec->gpio_data |= spec->gpio_led; |
725 | else | 374 | else |
726 | return 1; | 375 | spec->gpio_data &= ~spec->gpio_led; |
376 | stac_gpio_set(codec, spec->gpio_mask, | ||
377 | spec->gpio_dir, spec->gpio_data); | ||
378 | } else { | ||
379 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; | ||
380 | stac_vrefout_set(codec, spec->vref_mute_led_nid, | ||
381 | spec->vref_led); | ||
382 | } | ||
727 | } | 383 | } |
728 | 384 | ||
729 | static unsigned int stac92xx_vref_get(struct hda_codec *codec, hda_nid_t nid) | 385 | /* vmaster hook to update mute LED */ |
386 | static void stac_vmaster_hook(void *private_data, int val) | ||
730 | { | 387 | { |
731 | unsigned int vref; | 388 | stac_update_led_status(private_data, val); |
732 | vref = snd_hda_codec_read(codec, nid, 0, | ||
733 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
734 | vref &= AC_PINCTL_VREFEN; | ||
735 | return vref; | ||
736 | } | 389 | } |
737 | 390 | ||
738 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 391 | /* automute hook to handle GPIO mute and EAPD updates */ |
392 | static void stac_update_outputs(struct hda_codec *codec) | ||
739 | { | 393 | { |
740 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
741 | struct sigmatel_spec *spec = codec->spec; | 394 | struct sigmatel_spec *spec = codec->spec; |
742 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | 395 | |
396 | if (spec->gpio_mute) | ||
397 | spec->gen.master_mute = | ||
398 | !(snd_hda_codec_read(codec, codec->afg, 0, | ||
399 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); | ||
400 | |||
401 | snd_hda_gen_update_outputs(codec); | ||
402 | |||
403 | if (spec->eapd_mask && spec->eapd_switch) { | ||
404 | unsigned int val = spec->gpio_data; | ||
405 | if (spec->gen.speaker_muted) | ||
406 | val &= ~spec->eapd_mask; | ||
407 | else | ||
408 | val |= spec->eapd_mask; | ||
409 | if (spec->gpio_data != val) | ||
410 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, | ||
411 | val); | ||
412 | } | ||
743 | } | 413 | } |
744 | 414 | ||
745 | static int stac92xx_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 415 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
416 | bool enable, bool do_write) | ||
746 | { | 417 | { |
747 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
748 | struct sigmatel_spec *spec = codec->spec; | 418 | struct sigmatel_spec *spec = codec->spec; |
749 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 419 | unsigned int idx, val; |
750 | 420 | ||
751 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | 421 | for (idx = 0; idx < spec->num_pwrs; idx++) { |
752 | return 0; | 422 | if (spec->pwr_nids[idx] == nid) |
423 | break; | ||
424 | } | ||
425 | if (idx >= spec->num_pwrs) | ||
426 | return; | ||
427 | |||
428 | idx = 1 << idx; | ||
429 | |||
430 | val = spec->power_map_bits; | ||
431 | if (enable) | ||
432 | val &= ~idx; | ||
433 | else | ||
434 | val |= idx; | ||
435 | |||
436 | /* power down unused output ports */ | ||
437 | if (val != spec->power_map_bits) { | ||
438 | spec->power_map_bits = val; | ||
439 | if (do_write) | ||
440 | snd_hda_codec_write(codec, codec->afg, 0, | ||
441 | AC_VERB_IDT_SET_POWER_MAP, val); | ||
442 | } | ||
753 | } | 443 | } |
754 | 444 | ||
755 | static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 445 | /* update power bit per jack plug/unplug */ |
446 | static void jack_update_power(struct hda_codec *codec, | ||
447 | struct hda_jack_tbl *jack) | ||
756 | { | 448 | { |
757 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
758 | struct sigmatel_spec *spec = codec->spec; | 449 | struct sigmatel_spec *spec = codec->spec; |
759 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 450 | int i; |
760 | const struct hda_input_mux *imux = spec->input_mux; | 451 | |
761 | unsigned int idx, prev_idx, didx; | 452 | if (!spec->num_pwrs) |
762 | 453 | return; | |
763 | idx = ucontrol->value.enumerated.item[0]; | 454 | |
764 | if (idx >= imux->num_items) | 455 | if (jack && jack->nid) { |
765 | idx = imux->num_items - 1; | 456 | stac_toggle_power_map(codec, jack->nid, |
766 | prev_idx = spec->cur_mux[adc_idx]; | 457 | snd_hda_jack_detect(codec, jack->nid), |
767 | if (prev_idx == idx) | 458 | true); |
768 | return 0; | 459 | return; |
769 | if (idx < spec->num_analog_muxes) { | ||
770 | snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, | ||
771 | AC_VERB_SET_CONNECT_SEL, | ||
772 | imux->items[idx].index); | ||
773 | if (prev_idx >= spec->num_analog_muxes && | ||
774 | spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { | ||
775 | imux = spec->dinput_mux; | ||
776 | /* 0 = analog */ | ||
777 | snd_hda_codec_write_cache(codec, | ||
778 | spec->dmux_nids[adc_idx], 0, | ||
779 | AC_VERB_SET_CONNECT_SEL, | ||
780 | imux->items[0].index); | ||
781 | } | ||
782 | } else { | ||
783 | imux = spec->dinput_mux; | ||
784 | /* first dimux item is hardcoded to select analog imux, | ||
785 | * so lets skip it | ||
786 | */ | ||
787 | didx = idx - spec->num_analog_muxes + 1; | ||
788 | snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, | ||
789 | AC_VERB_SET_CONNECT_SEL, | ||
790 | imux->items[didx].index); | ||
791 | } | 460 | } |
792 | spec->cur_mux[adc_idx] = idx; | 461 | |
793 | return 1; | 462 | /* update all jacks */ |
463 | for (i = 0; i < spec->num_pwrs; i++) { | ||
464 | hda_nid_t nid = spec->pwr_nids[i]; | ||
465 | jack = snd_hda_jack_tbl_get(codec, nid); | ||
466 | if (!jack || !jack->action) | ||
467 | continue; | ||
468 | if (jack->action == STAC_PWR_EVENT || | ||
469 | jack->action <= HDA_GEN_LAST_EVENT) | ||
470 | stac_toggle_power_map(codec, nid, | ||
471 | snd_hda_jack_detect(codec, nid), | ||
472 | false); | ||
473 | } | ||
474 | |||
475 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, | ||
476 | spec->power_map_bits); | ||
794 | } | 477 | } |
795 | 478 | ||
796 | static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, | 479 | static void stac_hp_automute(struct hda_codec *codec, |
797 | struct snd_ctl_elem_info *uinfo) | 480 | struct hda_jack_tbl *jack) |
798 | { | 481 | { |
799 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 482 | snd_hda_gen_hp_automute(codec, jack); |
800 | struct sigmatel_spec *spec = codec->spec; | 483 | jack_update_power(codec, jack); |
801 | return snd_hda_input_mux_info(spec->mono_mux, uinfo); | ||
802 | } | 484 | } |
803 | 485 | ||
804 | static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol, | 486 | static void stac_line_automute(struct hda_codec *codec, |
805 | struct snd_ctl_elem_value *ucontrol) | 487 | struct hda_jack_tbl *jack) |
488 | { | ||
489 | snd_hda_gen_line_automute(codec, jack); | ||
490 | jack_update_power(codec, jack); | ||
491 | } | ||
492 | |||
493 | static void stac_vref_event(struct hda_codec *codec, struct hda_jack_tbl *event) | ||
494 | { | ||
495 | unsigned int data; | ||
496 | |||
497 | data = snd_hda_codec_read(codec, codec->afg, 0, | ||
498 | AC_VERB_GET_GPIO_DATA, 0); | ||
499 | /* toggle VREF state based on GPIOx status */ | ||
500 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | ||
501 | !!(data & (1 << event->private_data))); | ||
502 | } | ||
503 | |||
504 | /* initialize the power map and enable the power event to jacks that | ||
505 | * haven't been assigned to automute | ||
506 | */ | ||
507 | static void stac_init_power_map(struct hda_codec *codec) | ||
806 | { | 508 | { |
807 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
808 | struct sigmatel_spec *spec = codec->spec; | 509 | struct sigmatel_spec *spec = codec->spec; |
510 | int i; | ||
809 | 511 | ||
810 | ucontrol->value.enumerated.item[0] = spec->cur_mmux; | 512 | for (i = 0; i < spec->num_pwrs; i++) { |
811 | return 0; | 513 | hda_nid_t nid = spec->pwr_nids[i]; |
514 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
515 | def_conf = get_defcfg_connect(def_conf); | ||
516 | if (snd_hda_jack_tbl_get(codec, nid)) | ||
517 | continue; | ||
518 | if (def_conf == AC_JACK_PORT_COMPLEX && | ||
519 | !(spec->vref_mute_led_nid == nid || | ||
520 | is_jack_detectable(codec, nid))) { | ||
521 | snd_hda_jack_detect_enable_callback(codec, nid, | ||
522 | STAC_PWR_EVENT, | ||
523 | jack_update_power); | ||
524 | } else { | ||
525 | if (def_conf == AC_JACK_PORT_NONE) | ||
526 | stac_toggle_power_map(codec, nid, false, false); | ||
527 | else | ||
528 | stac_toggle_power_map(codec, nid, true, false); | ||
529 | } | ||
530 | } | ||
812 | } | 531 | } |
813 | 532 | ||
814 | static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, | 533 | /* |
815 | struct snd_ctl_elem_value *ucontrol) | 534 | */ |
535 | |||
536 | static inline bool get_int_hint(struct hda_codec *codec, const char *key, | ||
537 | int *valp) | ||
538 | { | ||
539 | return !snd_hda_get_int_hint(codec, key, valp); | ||
540 | } | ||
541 | |||
542 | /* override some hints from the hwdep entry */ | ||
543 | static void stac_store_hints(struct hda_codec *codec) | ||
816 | { | 544 | { |
817 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
818 | struct sigmatel_spec *spec = codec->spec; | 545 | struct sigmatel_spec *spec = codec->spec; |
546 | int val; | ||
819 | 547 | ||
820 | return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol, | 548 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { |
821 | spec->mono_nid, &spec->cur_mmux); | 549 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = |
550 | spec->gpio_mask; | ||
551 | } | ||
552 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) | ||
553 | spec->gpio_mask &= spec->gpio_mask; | ||
554 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) | ||
555 | spec->gpio_dir &= spec->gpio_mask; | ||
556 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) | ||
557 | spec->eapd_mask &= spec->gpio_mask; | ||
558 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) | ||
559 | spec->gpio_mute &= spec->gpio_mask; | ||
560 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | ||
561 | if (val >= 0) | ||
562 | spec->eapd_switch = val; | ||
822 | } | 563 | } |
823 | 564 | ||
824 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | 565 | /* |
566 | * loopback controls | ||
567 | */ | ||
568 | |||
569 | #define stac_aloopback_info snd_ctl_boolean_mono_info | ||
825 | 570 | ||
826 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | 571 | static int stac_aloopback_get(struct snd_kcontrol *kcontrol, |
827 | struct snd_ctl_elem_value *ucontrol) | 572 | struct snd_ctl_elem_value *ucontrol) |
828 | { | 573 | { |
829 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 574 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
830 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 575 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
@@ -835,8 +580,8 @@ static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | |||
835 | return 0; | 580 | return 0; |
836 | } | 581 | } |
837 | 582 | ||
838 | static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | 583 | static int stac_aloopback_put(struct snd_kcontrol *kcontrol, |
839 | struct snd_ctl_elem_value *ucontrol) | 584 | struct snd_ctl_elem_value *ucontrol) |
840 | { | 585 | { |
841 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 586 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
842 | struct sigmatel_spec *spec = codec->spec; | 587 | struct sigmatel_spec *spec = codec->spec; |
@@ -875,6 +620,267 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | |||
875 | return 1; | 620 | return 1; |
876 | } | 621 | } |
877 | 622 | ||
623 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | ||
624 | { \ | ||
625 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
626 | .name = "Analog Loopback", \ | ||
627 | .count = cnt, \ | ||
628 | .info = stac_aloopback_info, \ | ||
629 | .get = stac_aloopback_get, \ | ||
630 | .put = stac_aloopback_put, \ | ||
631 | .private_value = verb_read | (verb_write << 16), \ | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * Mute LED handling on HP laptops | ||
636 | */ | ||
637 | |||
638 | /* check whether it's a HP laptop with a docking port */ | ||
639 | static bool hp_bnb2011_with_dock(struct hda_codec *codec) | ||
640 | { | ||
641 | if (codec->vendor_id != 0x111d7605 && | ||
642 | codec->vendor_id != 0x111d76d1) | ||
643 | return false; | ||
644 | |||
645 | switch (codec->subsystem_id) { | ||
646 | case 0x103c1618: | ||
647 | case 0x103c1619: | ||
648 | case 0x103c161a: | ||
649 | case 0x103c161b: | ||
650 | case 0x103c161c: | ||
651 | case 0x103c161d: | ||
652 | case 0x103c161e: | ||
653 | case 0x103c161f: | ||
654 | |||
655 | case 0x103c162a: | ||
656 | case 0x103c162b: | ||
657 | |||
658 | case 0x103c1630: | ||
659 | case 0x103c1631: | ||
660 | |||
661 | case 0x103c1633: | ||
662 | case 0x103c1634: | ||
663 | case 0x103c1635: | ||
664 | |||
665 | case 0x103c3587: | ||
666 | case 0x103c3588: | ||
667 | case 0x103c3589: | ||
668 | case 0x103c358a: | ||
669 | |||
670 | case 0x103c3667: | ||
671 | case 0x103c3668: | ||
672 | case 0x103c3669: | ||
673 | |||
674 | return true; | ||
675 | } | ||
676 | return false; | ||
677 | } | ||
678 | |||
679 | static bool hp_blike_system(u32 subsystem_id) | ||
680 | { | ||
681 | switch (subsystem_id) { | ||
682 | case 0x103c1520: | ||
683 | case 0x103c1521: | ||
684 | case 0x103c1523: | ||
685 | case 0x103c1524: | ||
686 | case 0x103c1525: | ||
687 | case 0x103c1722: | ||
688 | case 0x103c1723: | ||
689 | case 0x103c1724: | ||
690 | case 0x103c1725: | ||
691 | case 0x103c1726: | ||
692 | case 0x103c1727: | ||
693 | case 0x103c1728: | ||
694 | case 0x103c1729: | ||
695 | case 0x103c172a: | ||
696 | case 0x103c172b: | ||
697 | case 0x103c307e: | ||
698 | case 0x103c307f: | ||
699 | case 0x103c3080: | ||
700 | case 0x103c3081: | ||
701 | case 0x103c7007: | ||
702 | case 0x103c7008: | ||
703 | return true; | ||
704 | } | ||
705 | return false; | ||
706 | } | ||
707 | |||
708 | static void set_hp_led_gpio(struct hda_codec *codec) | ||
709 | { | ||
710 | struct sigmatel_spec *spec = codec->spec; | ||
711 | unsigned int gpio; | ||
712 | |||
713 | if (spec->gpio_led) | ||
714 | return; | ||
715 | |||
716 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); | ||
717 | gpio &= AC_GPIO_IO_COUNT; | ||
718 | if (gpio > 3) | ||
719 | spec->gpio_led = 0x08; /* GPIO 3 */ | ||
720 | else | ||
721 | spec->gpio_led = 0x01; /* GPIO 0 */ | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * This method searches for the mute LED GPIO configuration | ||
726 | * provided as OEM string in SMBIOS. The format of that string | ||
727 | * is HP_Mute_LED_P_G or HP_Mute_LED_P | ||
728 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) | ||
729 | * that corresponds to the NOT muted state of the master volume | ||
730 | * and G is the index of the GPIO to use as the mute LED control (0..9) | ||
731 | * If _G portion is missing it is assigned based on the codec ID | ||
732 | * | ||
733 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) | ||
734 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings | ||
735 | * | ||
736 | * | ||
737 | * The dv-series laptops don't seem to have the HP_Mute_LED* strings in | ||
738 | * SMBIOS - at least the ones I have seen do not have them - which include | ||
739 | * my own system (HP Pavilion dv6-1110ax) and my cousin's | ||
740 | * HP Pavilion dv9500t CTO. | ||
741 | * Need more information on whether it is true across the entire series. | ||
742 | * -- kunal | ||
743 | */ | ||
744 | static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) | ||
745 | { | ||
746 | struct sigmatel_spec *spec = codec->spec; | ||
747 | const struct dmi_device *dev = NULL; | ||
748 | |||
749 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | ||
750 | get_int_hint(codec, "gpio_led_polarity", | ||
751 | &spec->gpio_led_polarity); | ||
752 | return 1; | ||
753 | } | ||
754 | |||
755 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { | ||
756 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", | ||
757 | &spec->gpio_led_polarity, | ||
758 | &spec->gpio_led) == 2) { | ||
759 | unsigned int max_gpio; | ||
760 | max_gpio = snd_hda_param_read(codec, codec->afg, | ||
761 | AC_PAR_GPIO_CAP); | ||
762 | max_gpio &= AC_GPIO_IO_COUNT; | ||
763 | if (spec->gpio_led < max_gpio) | ||
764 | spec->gpio_led = 1 << spec->gpio_led; | ||
765 | else | ||
766 | spec->vref_mute_led_nid = spec->gpio_led; | ||
767 | return 1; | ||
768 | } | ||
769 | if (sscanf(dev->name, "HP_Mute_LED_%d", | ||
770 | &spec->gpio_led_polarity) == 1) { | ||
771 | set_hp_led_gpio(codec); | ||
772 | return 1; | ||
773 | } | ||
774 | /* BIOS bug: unfilled OEM string */ | ||
775 | if (strstr(dev->name, "HP_Mute_LED_P_G")) { | ||
776 | set_hp_led_gpio(codec); | ||
777 | if (default_polarity >= 0) | ||
778 | spec->gpio_led_polarity = default_polarity; | ||
779 | else | ||
780 | spec->gpio_led_polarity = 1; | ||
781 | return 1; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Fallback case - if we don't find the DMI strings, | ||
787 | * we statically set the GPIO - if not a B-series system | ||
788 | * and default polarity is provided | ||
789 | */ | ||
790 | if (!hp_blike_system(codec->subsystem_id) && | ||
791 | (default_polarity == 0 || default_polarity == 1)) { | ||
792 | set_hp_led_gpio(codec); | ||
793 | spec->gpio_led_polarity = default_polarity; | ||
794 | return 1; | ||
795 | } | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * PC beep controls | ||
801 | */ | ||
802 | |||
803 | /* create PC beep volume controls */ | ||
804 | static int stac_auto_create_beep_ctls(struct hda_codec *codec, | ||
805 | hda_nid_t nid) | ||
806 | { | ||
807 | struct sigmatel_spec *spec = codec->spec; | ||
808 | u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); | ||
809 | struct snd_kcontrol_new *knew; | ||
810 | static struct snd_kcontrol_new abeep_mute_ctl = | ||
811 | HDA_CODEC_MUTE(NULL, 0, 0, 0); | ||
812 | static struct snd_kcontrol_new dbeep_mute_ctl = | ||
813 | HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0); | ||
814 | static struct snd_kcontrol_new beep_vol_ctl = | ||
815 | HDA_CODEC_VOLUME(NULL, 0, 0, 0); | ||
816 | |||
817 | /* check for mute support for the the amp */ | ||
818 | if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { | ||
819 | const struct snd_kcontrol_new *temp; | ||
820 | if (spec->anabeep_nid == nid) | ||
821 | temp = &abeep_mute_ctl; | ||
822 | else | ||
823 | temp = &dbeep_mute_ctl; | ||
824 | knew = snd_hda_gen_add_kctl(&spec->gen, | ||
825 | "Beep Playback Switch", temp); | ||
826 | if (!knew) | ||
827 | return -ENOMEM; | ||
828 | knew->private_value = | ||
829 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); | ||
830 | } | ||
831 | |||
832 | /* check to see if there is volume support for the amp */ | ||
833 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { | ||
834 | knew = snd_hda_gen_add_kctl(&spec->gen, | ||
835 | "Beep Playback Volume", | ||
836 | &beep_vol_ctl); | ||
837 | if (!knew) | ||
838 | return -ENOMEM; | ||
839 | knew->private_value = | ||
840 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); | ||
841 | } | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
846 | #define stac_dig_beep_switch_info snd_ctl_boolean_mono_info | ||
847 | |||
848 | static int stac_dig_beep_switch_get(struct snd_kcontrol *kcontrol, | ||
849 | struct snd_ctl_elem_value *ucontrol) | ||
850 | { | ||
851 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
852 | ucontrol->value.integer.value[0] = codec->beep->enabled; | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static int stac_dig_beep_switch_put(struct snd_kcontrol *kcontrol, | ||
857 | struct snd_ctl_elem_value *ucontrol) | ||
858 | { | ||
859 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
860 | return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]); | ||
861 | } | ||
862 | |||
863 | static const struct snd_kcontrol_new stac_dig_beep_ctrl = { | ||
864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
865 | .name = "Beep Playback Switch", | ||
866 | .info = stac_dig_beep_switch_info, | ||
867 | .get = stac_dig_beep_switch_get, | ||
868 | .put = stac_dig_beep_switch_put, | ||
869 | }; | ||
870 | |||
871 | static int stac_beep_switch_ctl(struct hda_codec *codec) | ||
872 | { | ||
873 | struct sigmatel_spec *spec = codec->spec; | ||
874 | |||
875 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_dig_beep_ctrl)) | ||
876 | return -ENOMEM; | ||
877 | return 0; | ||
878 | } | ||
879 | #endif | ||
880 | |||
881 | /* | ||
882 | */ | ||
883 | |||
878 | static const struct hda_verb stac9200_core_init[] = { | 884 | static const struct hda_verb stac9200_core_init[] = { |
879 | /* set dac0mux for dac converter */ | 885 | /* set dac0mux for dac converter */ |
880 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 886 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -937,7 +943,7 @@ static const struct hda_verb stac925x_core_init[] = { | |||
937 | }; | 943 | }; |
938 | 944 | ||
939 | static const struct hda_verb stac922x_core_init[] = { | 945 | static const struct hda_verb stac922x_core_init[] = { |
940 | /* set master volume and direct control */ | 946 | /* set master volume and direct control */ |
941 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 947 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
942 | {} | 948 | {} |
943 | }; | 949 | }; |
@@ -945,7 +951,7 @@ static const struct hda_verb stac922x_core_init[] = { | |||
945 | static const struct hda_verb d965_core_init[] = { | 951 | static const struct hda_verb d965_core_init[] = { |
946 | /* unmute node 0x1b */ | 952 | /* unmute node 0x1b */ |
947 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 953 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
948 | /* select node 0x03 as DAC */ | 954 | /* select node 0x03 as DAC */ |
949 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | 955 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, |
950 | {} | 956 | {} |
951 | }; | 957 | }; |
@@ -961,7 +967,7 @@ static const struct hda_verb dell_3st_core_init[] = { | |||
961 | }; | 967 | }; |
962 | 968 | ||
963 | static const struct hda_verb stac927x_core_init[] = { | 969 | static const struct hda_verb stac927x_core_init[] = { |
964 | /* set master volume and direct control */ | 970 | /* set master volume and direct control */ |
965 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 971 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
966 | /* enable analog pc beep path */ | 972 | /* enable analog pc beep path */ |
967 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 973 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, |
@@ -977,224 +983,30 @@ static const struct hda_verb stac927x_volknob_core_init[] = { | |||
977 | }; | 983 | }; |
978 | 984 | ||
979 | static const struct hda_verb stac9205_core_init[] = { | 985 | static const struct hda_verb stac9205_core_init[] = { |
980 | /* set master volume and direct control */ | 986 | /* set master volume and direct control */ |
981 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 987 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
982 | /* enable analog pc beep path */ | 988 | /* enable analog pc beep path */ |
983 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 989 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, |
984 | {} | 990 | {} |
985 | }; | 991 | }; |
986 | 992 | ||
987 | #define STAC_MONO_MUX \ | 993 | static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback = |
988 | { \ | 994 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3); |
989 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
990 | .name = "Mono Mux", \ | ||
991 | .count = 1, \ | ||
992 | .info = stac92xx_mono_mux_enum_info, \ | ||
993 | .get = stac92xx_mono_mux_enum_get, \ | ||
994 | .put = stac92xx_mono_mux_enum_put, \ | ||
995 | } | ||
996 | |||
997 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | ||
998 | { \ | ||
999 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1000 | .name = "Analog Loopback", \ | ||
1001 | .count = cnt, \ | ||
1002 | .info = stac92xx_aloopback_info, \ | ||
1003 | .get = stac92xx_aloopback_get, \ | ||
1004 | .put = stac92xx_aloopback_put, \ | ||
1005 | .private_value = verb_read | (verb_write << 16), \ | ||
1006 | } | ||
1007 | |||
1008 | #define DC_BIAS(xname, idx, nid) \ | ||
1009 | { \ | ||
1010 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1011 | .name = xname, \ | ||
1012 | .index = idx, \ | ||
1013 | .info = stac92xx_dc_bias_info, \ | ||
1014 | .get = stac92xx_dc_bias_get, \ | ||
1015 | .put = stac92xx_dc_bias_put, \ | ||
1016 | .private_value = nid, \ | ||
1017 | } | ||
1018 | |||
1019 | static const struct snd_kcontrol_new stac9200_mixer[] = { | ||
1020 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT), | ||
1021 | HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT), | ||
1022 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | ||
1023 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | ||
1024 | { } /* end */ | ||
1025 | }; | ||
1026 | |||
1027 | static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = { | ||
1028 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
1029 | {} | ||
1030 | }; | ||
1031 | |||
1032 | static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = { | ||
1033 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), | ||
1034 | {} | ||
1035 | }; | ||
1036 | |||
1037 | static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { | ||
1038 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
1039 | {} | ||
1040 | }; | ||
1041 | 995 | ||
996 | static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback = | ||
997 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4); | ||
1042 | 998 | ||
1043 | static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = { | 999 | static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback = |
1044 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) | 1000 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5); |
1045 | }; | ||
1046 | 1001 | ||
1047 | static const struct snd_kcontrol_new stac925x_mixer[] = { | 1002 | static const struct snd_kcontrol_new stac92hd71bxx_loopback = |
1048 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT), | 1003 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2); |
1049 | HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT), | ||
1050 | { } /* end */ | ||
1051 | }; | ||
1052 | 1004 | ||
1053 | static const struct snd_kcontrol_new stac9205_loopback[] = { | 1005 | static const struct snd_kcontrol_new stac9205_loopback = |
1054 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | 1006 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1); |
1055 | {} | ||
1056 | }; | ||
1057 | |||
1058 | static const struct snd_kcontrol_new stac927x_loopback[] = { | ||
1059 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | ||
1060 | {} | ||
1061 | }; | ||
1062 | |||
1063 | static struct snd_kcontrol_new stac_dmux_mixer = { | ||
1064 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1065 | .name = "Digital Input Source", | ||
1066 | /* count set later */ | ||
1067 | .info = stac92xx_dmux_enum_info, | ||
1068 | .get = stac92xx_dmux_enum_get, | ||
1069 | .put = stac92xx_dmux_enum_put, | ||
1070 | }; | ||
1071 | |||
1072 | static struct snd_kcontrol_new stac_smux_mixer = { | ||
1073 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1074 | .name = "IEC958 Playback Source", | ||
1075 | /* count set later */ | ||
1076 | .info = stac92xx_smux_enum_info, | ||
1077 | .get = stac92xx_smux_enum_get, | ||
1078 | .put = stac92xx_smux_enum_put, | ||
1079 | }; | ||
1080 | |||
1081 | static const char * const slave_pfxs[] = { | ||
1082 | "Front", "Surround", "Center", "LFE", "Side", | ||
1083 | "Headphone", "Speaker", "Bass Speaker", "IEC958", "PCM", | ||
1084 | NULL | ||
1085 | }; | ||
1086 | 1007 | ||
1087 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled); | 1008 | static const struct snd_kcontrol_new stac927x_loopback = |
1088 | 1009 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1); | |
1089 | static void stac92xx_vmaster_hook(void *private_data, int val) | ||
1090 | { | ||
1091 | stac92xx_update_led_status(private_data, val); | ||
1092 | } | ||
1093 | |||
1094 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1095 | |||
1096 | static int stac92xx_build_controls(struct hda_codec *codec) | ||
1097 | { | ||
1098 | struct sigmatel_spec *spec = codec->spec; | ||
1099 | unsigned int vmaster_tlv[4]; | ||
1100 | int err; | ||
1101 | int i; | ||
1102 | |||
1103 | if (spec->mixer) { | ||
1104 | err = snd_hda_add_new_ctls(codec, spec->mixer); | ||
1105 | if (err < 0) | ||
1106 | return err; | ||
1107 | } | ||
1108 | |||
1109 | for (i = 0; i < spec->num_mixers; i++) { | ||
1110 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
1111 | if (err < 0) | ||
1112 | return err; | ||
1113 | } | ||
1114 | if (!spec->auto_mic && spec->num_dmuxes > 0 && | ||
1115 | snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { | ||
1116 | stac_dmux_mixer.count = spec->num_dmuxes; | ||
1117 | err = snd_hda_ctl_add(codec, 0, | ||
1118 | snd_ctl_new1(&stac_dmux_mixer, codec)); | ||
1119 | if (err < 0) | ||
1120 | return err; | ||
1121 | } | ||
1122 | if (spec->num_smuxes > 0) { | ||
1123 | int wcaps = get_wcaps(codec, spec->multiout.dig_out_nid); | ||
1124 | struct hda_input_mux *smux = &spec->private_smux; | ||
1125 | /* check for mute support on SPDIF out */ | ||
1126 | if (wcaps & AC_WCAP_OUT_AMP) { | ||
1127 | snd_hda_add_imux_item(smux, "Off", 0, NULL); | ||
1128 | spec->spdif_mute = 1; | ||
1129 | } | ||
1130 | stac_smux_mixer.count = spec->num_smuxes; | ||
1131 | err = snd_hda_ctl_add(codec, 0, | ||
1132 | snd_ctl_new1(&stac_smux_mixer, codec)); | ||
1133 | if (err < 0) | ||
1134 | return err; | ||
1135 | } | ||
1136 | |||
1137 | if (spec->multiout.dig_out_nid) { | ||
1138 | err = snd_hda_create_dig_out_ctls(codec, | ||
1139 | spec->multiout.dig_out_nid, | ||
1140 | spec->multiout.dig_out_nid, | ||
1141 | spec->autocfg.dig_out_type[0]); | ||
1142 | if (err < 0) | ||
1143 | return err; | ||
1144 | err = snd_hda_create_spdif_share_sw(codec, | ||
1145 | &spec->multiout); | ||
1146 | if (err < 0) | ||
1147 | return err; | ||
1148 | spec->multiout.share_spdif = 1; | ||
1149 | } | ||
1150 | if (spec->dig_in_nid && !(spec->gpio_dir & 0x01)) { | ||
1151 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | ||
1152 | if (err < 0) | ||
1153 | return err; | ||
1154 | } | ||
1155 | |||
1156 | /* if we have no master control, let's create it */ | ||
1157 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | ||
1158 | HDA_OUTPUT, vmaster_tlv); | ||
1159 | /* correct volume offset */ | ||
1160 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | ||
1161 | /* minimum value is actually mute */ | ||
1162 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
1163 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
1164 | vmaster_tlv, slave_pfxs, | ||
1165 | "Playback Volume"); | ||
1166 | if (err < 0) | ||
1167 | return err; | ||
1168 | |||
1169 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
1170 | NULL, slave_pfxs, | ||
1171 | "Playback Switch", true, | ||
1172 | &spec->vmaster_mute.sw_kctl); | ||
1173 | if (err < 0) | ||
1174 | return err; | ||
1175 | |||
1176 | if (spec->gpio_led) { | ||
1177 | spec->vmaster_mute.hook = stac92xx_vmaster_hook; | ||
1178 | err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); | ||
1179 | if (err < 0) | ||
1180 | return err; | ||
1181 | } | ||
1182 | |||
1183 | if (spec->aloopback_ctl && | ||
1184 | snd_hda_get_bool_hint(codec, "loopback") == 1) { | ||
1185 | err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl); | ||
1186 | if (err < 0) | ||
1187 | return err; | ||
1188 | } | ||
1189 | |||
1190 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1191 | |||
1192 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | ||
1193 | if (err < 0) | ||
1194 | return err; | ||
1195 | |||
1196 | return 0; | ||
1197 | } | ||
1198 | 1010 | ||
1199 | static const struct hda_pintbl ref9200_pin_configs[] = { | 1011 | static const struct hda_pintbl ref9200_pin_configs[] = { |
1200 | { 0x08, 0x01c47010 }, | 1012 | { 0x08, 0x01c47010 }, |
@@ -1250,7 +1062,7 @@ static const struct hda_pintbl dell9200_d21_pin_configs[] = { | |||
1250 | {} | 1062 | {} |
1251 | }; | 1063 | }; |
1252 | 1064 | ||
1253 | /* | 1065 | /* |
1254 | STAC 9200 pin configs for | 1066 | STAC 9200 pin configs for |
1255 | 102801C0 | 1067 | 102801C0 |
1256 | 102801C1 | 1068 | 102801C1 |
@@ -1267,7 +1079,7 @@ static const struct hda_pintbl dell9200_d22_pin_configs[] = { | |||
1267 | {} | 1079 | {} |
1268 | }; | 1080 | }; |
1269 | 1081 | ||
1270 | /* | 1082 | /* |
1271 | STAC 9200 pin configs for | 1083 | STAC 9200 pin configs for |
1272 | 102801C4 (Dell Dimension E310) | 1084 | 102801C4 (Dell Dimension E310) |
1273 | 102801C5 | 1085 | 102801C5 |
@@ -1431,17 +1243,13 @@ static void stac9200_fixup_panasonic(struct hda_codec *codec, | |||
1431 | { | 1243 | { |
1432 | struct sigmatel_spec *spec = codec->spec; | 1244 | struct sigmatel_spec *spec = codec->spec; |
1433 | 1245 | ||
1434 | switch (action) { | 1246 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
1435 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
1436 | spec->gpio_mask = spec->gpio_dir = 0x09; | 1247 | spec->gpio_mask = spec->gpio_dir = 0x09; |
1437 | spec->gpio_data = 0x00; | 1248 | spec->gpio_data = 0x00; |
1438 | break; | ||
1439 | case HDA_FIXUP_ACT_PROBE: | ||
1440 | /* CF-74 has no headphone detection, and the driver should *NOT* | 1249 | /* CF-74 has no headphone detection, and the driver should *NOT* |
1441 | * do detection and HP/speaker toggle because the hardware does it. | 1250 | * do detection and HP/speaker toggle because the hardware does it. |
1442 | */ | 1251 | */ |
1443 | spec->hp_detect = 0; | 1252 | spec->gen.suppress_auto_mute = 1; |
1444 | break; | ||
1445 | } | 1253 | } |
1446 | } | 1254 | } |
1447 | 1255 | ||
@@ -1862,7 +1670,6 @@ static void stac92hd73xx_fixup_dell(struct hda_codec *codec) | |||
1862 | struct sigmatel_spec *spec = codec->spec; | 1670 | struct sigmatel_spec *spec = codec->spec; |
1863 | 1671 | ||
1864 | snd_hda_apply_pincfgs(codec, dell_m6_pin_configs); | 1672 | snd_hda_apply_pincfgs(codec, dell_m6_pin_configs); |
1865 | spec->num_smuxes = 0; | ||
1866 | spec->eapd_switch = 0; | 1673 | spec->eapd_switch = 0; |
1867 | } | 1674 | } |
1868 | 1675 | ||
@@ -1883,43 +1690,34 @@ static void stac92hd73xx_fixup_dell_eq(struct hda_codec *codec, | |||
1883 | static void stac92hd73xx_fixup_dell_m6_amic(struct hda_codec *codec, | 1690 | static void stac92hd73xx_fixup_dell_m6_amic(struct hda_codec *codec, |
1884 | const struct hda_fixup *fix, int action) | 1691 | const struct hda_fixup *fix, int action) |
1885 | { | 1692 | { |
1886 | struct sigmatel_spec *spec = codec->spec; | ||
1887 | |||
1888 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1693 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1889 | return; | 1694 | return; |
1890 | 1695 | ||
1891 | stac92hd73xx_fixup_dell(codec); | 1696 | stac92hd73xx_fixup_dell(codec); |
1892 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); | 1697 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
1893 | spec->num_dmics = 0; | ||
1894 | } | 1698 | } |
1895 | 1699 | ||
1896 | /* Digital Mics */ | 1700 | /* Digital Mics */ |
1897 | static void stac92hd73xx_fixup_dell_m6_dmic(struct hda_codec *codec, | 1701 | static void stac92hd73xx_fixup_dell_m6_dmic(struct hda_codec *codec, |
1898 | const struct hda_fixup *fix, int action) | 1702 | const struct hda_fixup *fix, int action) |
1899 | { | 1703 | { |
1900 | struct sigmatel_spec *spec = codec->spec; | ||
1901 | |||
1902 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1704 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1903 | return; | 1705 | return; |
1904 | 1706 | ||
1905 | stac92hd73xx_fixup_dell(codec); | 1707 | stac92hd73xx_fixup_dell(codec); |
1906 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); | 1708 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
1907 | spec->num_dmics = 1; | ||
1908 | } | 1709 | } |
1909 | 1710 | ||
1910 | /* Both */ | 1711 | /* Both */ |
1911 | static void stac92hd73xx_fixup_dell_m6_both(struct hda_codec *codec, | 1712 | static void stac92hd73xx_fixup_dell_m6_both(struct hda_codec *codec, |
1912 | const struct hda_fixup *fix, int action) | 1713 | const struct hda_fixup *fix, int action) |
1913 | { | 1714 | { |
1914 | struct sigmatel_spec *spec = codec->spec; | ||
1915 | |||
1916 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1715 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1917 | return; | 1716 | return; |
1918 | 1717 | ||
1919 | stac92hd73xx_fixup_dell(codec); | 1718 | stac92hd73xx_fixup_dell(codec); |
1920 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); | 1719 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
1921 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); | 1720 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
1922 | spec->num_dmics = 1; | ||
1923 | } | 1721 | } |
1924 | 1722 | ||
1925 | static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec, | 1723 | static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec, |
@@ -1931,19 +1729,14 @@ static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec, | |||
1931 | return; | 1729 | return; |
1932 | 1730 | ||
1933 | snd_hda_apply_pincfgs(codec, alienware_m17x_pin_configs); | 1731 | snd_hda_apply_pincfgs(codec, alienware_m17x_pin_configs); |
1934 | spec->num_dmics = STAC92HD73XX_NUM_DMICS; | ||
1935 | spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); | ||
1936 | spec->eapd_switch = 0; | 1732 | spec->eapd_switch = 0; |
1937 | } | 1733 | } |
1938 | 1734 | ||
1939 | static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec, | 1735 | static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec, |
1940 | const struct hda_fixup *fix, int action) | 1736 | const struct hda_fixup *fix, int action) |
1941 | { | 1737 | { |
1942 | struct sigmatel_spec *spec = codec->spec; | 1738 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
1943 | 1739 | codec->no_jack_detect = 1; | |
1944 | if (action != HDA_FIXUP_ACT_PROBE) | ||
1945 | return; | ||
1946 | spec->hp_detect = 0; | ||
1947 | } | 1740 | } |
1948 | 1741 | ||
1949 | static const struct hda_fixup stac92hd73xx_fixups[] = { | 1742 | static const struct hda_fixup stac92hd73xx_fixups[] = { |
@@ -2348,6 +2141,54 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2348 | {} /* terminator */ | 2141 | {} /* terminator */ |
2349 | }; | 2142 | }; |
2350 | 2143 | ||
2144 | /* HP dv7 bass switch - GPIO5 */ | ||
2145 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | ||
2146 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | ||
2147 | struct snd_ctl_elem_value *ucontrol) | ||
2148 | { | ||
2149 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2150 | struct sigmatel_spec *spec = codec->spec; | ||
2151 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | ||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | ||
2156 | struct snd_ctl_elem_value *ucontrol) | ||
2157 | { | ||
2158 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2159 | struct sigmatel_spec *spec = codec->spec; | ||
2160 | unsigned int gpio_data; | ||
2161 | |||
2162 | gpio_data = (spec->gpio_data & ~0x20) | | ||
2163 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | ||
2164 | if (gpio_data == spec->gpio_data) | ||
2165 | return 0; | ||
2166 | spec->gpio_data = gpio_data; | ||
2167 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | ||
2168 | return 1; | ||
2169 | } | ||
2170 | |||
2171 | static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | ||
2172 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2173 | .info = stac_hp_bass_gpio_info, | ||
2174 | .get = stac_hp_bass_gpio_get, | ||
2175 | .put = stac_hp_bass_gpio_put, | ||
2176 | }; | ||
2177 | |||
2178 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | ||
2179 | { | ||
2180 | struct sigmatel_spec *spec = codec->spec; | ||
2181 | |||
2182 | if (!snd_hda_gen_add_kctl(&spec->gen, "Bass Speaker Playback Switch", | ||
2183 | &stac_hp_bass_sw_ctrl)) | ||
2184 | return -ENOMEM; | ||
2185 | |||
2186 | spec->gpio_mask |= 0x20; | ||
2187 | spec->gpio_dir |= 0x20; | ||
2188 | spec->gpio_data |= 0x20; | ||
2189 | return 0; | ||
2190 | } | ||
2191 | |||
2351 | static const struct hda_pintbl ref92hd71bxx_pin_configs[] = { | 2192 | static const struct hda_pintbl ref92hd71bxx_pin_configs[] = { |
2352 | { 0x0a, 0x02214030 }, | 2193 | { 0x0a, 0x02214030 }, |
2353 | { 0x0b, 0x02a19040 }, | 2194 | { 0x0b, 0x02a19040 }, |
@@ -2420,66 +2261,29 @@ static void stac92hd71bxx_fixup_ref(struct hda_codec *codec, | |||
2420 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; | 2261 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; |
2421 | } | 2262 | } |
2422 | 2263 | ||
2423 | static void stac92hd71bxx_fixup_no_dmic(struct hda_codec *codec, | ||
2424 | const struct hda_fixup *fix, int action) | ||
2425 | { | ||
2426 | struct sigmatel_spec *spec = codec->spec; | ||
2427 | |||
2428 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
2429 | return; | ||
2430 | spec->num_dmics = 0; | ||
2431 | spec->num_smuxes = 0; | ||
2432 | spec->num_dmuxes = 0; | ||
2433 | } | ||
2434 | |||
2435 | static void stac92hd71bxx_fixup_no_smux(struct hda_codec *codec, | ||
2436 | const struct hda_fixup *fix, int action) | ||
2437 | { | ||
2438 | struct sigmatel_spec *spec = codec->spec; | ||
2439 | |||
2440 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
2441 | return; | ||
2442 | spec->num_dmics = 1; | ||
2443 | spec->num_smuxes = 0; | ||
2444 | spec->num_dmuxes = 1; | ||
2445 | } | ||
2446 | |||
2447 | static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, | 2264 | static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, |
2448 | const struct hda_fixup *fix, int action) | 2265 | const struct hda_fixup *fix, int action) |
2449 | { | 2266 | { |
2450 | struct sigmatel_spec *spec = codec->spec; | 2267 | struct sigmatel_spec *spec = codec->spec; |
2268 | struct hda_jack_tbl *jack; | ||
2451 | 2269 | ||
2452 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2270 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2453 | return; | 2271 | return; |
2454 | 2272 | ||
2455 | /* Enable VREF power saving on GPIO1 detect */ | 2273 | /* Enable VREF power saving on GPIO1 detect */ |
2456 | stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x02); | ||
2457 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 2274 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
2458 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 2275 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
2459 | snd_hda_jack_detect_enable(codec, codec->afg, 0); | 2276 | snd_hda_jack_detect_enable_callback(codec, codec->afg, |
2277 | STAC_VREF_EVENT, | ||
2278 | stac_vref_event); | ||
2279 | jack = snd_hda_jack_tbl_get(codec, codec->afg); | ||
2280 | if (jack) | ||
2281 | jack->private_data = 0x02; | ||
2282 | |||
2460 | spec->gpio_mask |= 0x02; | 2283 | spec->gpio_mask |= 0x02; |
2461 | 2284 | ||
2462 | /* enable internal microphone */ | 2285 | /* enable internal microphone */ |
2463 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); | 2286 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); |
2464 | stac92xx_auto_set_pinctl(codec, 0x0e, | ||
2465 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | ||
2466 | |||
2467 | stac92hd71bxx_fixup_no_dmic(codec, fix, action); | ||
2468 | } | ||
2469 | |||
2470 | static void stac92hd71bxx_fixup_hp_dv4_1222nr(struct hda_codec *codec, | ||
2471 | const struct hda_fixup *fix, int action) | ||
2472 | { | ||
2473 | struct sigmatel_spec *spec = codec->spec; | ||
2474 | |||
2475 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
2476 | return; | ||
2477 | spec->num_dmics = 1; | ||
2478 | /* I don't know if it needs 1 or 2 smuxes - will wait for | ||
2479 | * bug reports to fix if needed | ||
2480 | */ | ||
2481 | spec->num_smuxes = 1; | ||
2482 | spec->num_dmuxes = 1; | ||
2483 | } | 2287 | } |
2484 | 2288 | ||
2485 | static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec, | 2289 | static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec, |
@@ -2495,21 +2299,14 @@ static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec, | |||
2495 | static void stac92hd71bxx_fixup_hp_dv5(struct hda_codec *codec, | 2299 | static void stac92hd71bxx_fixup_hp_dv5(struct hda_codec *codec, |
2496 | const struct hda_fixup *fix, int action) | 2300 | const struct hda_fixup *fix, int action) |
2497 | { | 2301 | { |
2498 | struct sigmatel_spec *spec = codec->spec; | ||
2499 | unsigned int cap; | 2302 | unsigned int cap; |
2500 | 2303 | ||
2501 | switch (action) { | 2304 | switch (action) { |
2502 | case HDA_FIXUP_ACT_PRE_PROBE: | 2305 | case HDA_FIXUP_ACT_PRE_PROBE: |
2503 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); | 2306 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); |
2504 | stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); | ||
2505 | break; | 2307 | break; |
2506 | 2308 | ||
2507 | case HDA_FIXUP_ACT_PROBE: | 2309 | case HDA_FIXUP_ACT_PROBE: |
2508 | /* HP dv6 gives the headphone pin as a line-out. Thus we | ||
2509 | * need to set hp_detect flag here to force to enable HP | ||
2510 | * detection. | ||
2511 | */ | ||
2512 | spec->hp_detect = 1; | ||
2513 | /* enable bass on HP dv7 */ | 2310 | /* enable bass on HP dv7 */ |
2514 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | 2311 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); |
2515 | cap &= AC_GPIO_IO_COUNT; | 2312 | cap &= AC_GPIO_IO_COUNT; |
@@ -2527,9 +2324,6 @@ static void stac92hd71bxx_fixup_hp_hdx(struct hda_codec *codec, | |||
2527 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2324 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2528 | return; | 2325 | return; |
2529 | spec->gpio_led = 0x08; | 2326 | spec->gpio_led = 0x08; |
2530 | spec->num_dmics = 1; | ||
2531 | spec->num_smuxes = 1; | ||
2532 | spec->num_dmuxes = 1; | ||
2533 | } | 2327 | } |
2534 | 2328 | ||
2535 | 2329 | ||
@@ -2559,7 +2353,7 @@ static void stac92hd71bxx_fixup_hp(struct hda_codec *codec, | |||
2559 | } | 2353 | } |
2560 | } | 2354 | } |
2561 | 2355 | ||
2562 | if (find_mute_led_cfg(codec, spec->default_polarity)) | 2356 | if (find_mute_led_cfg(codec, 1)) |
2563 | snd_printd("mute LED gpio %d polarity %d\n", | 2357 | snd_printd("mute LED gpio %d polarity %d\n", |
2564 | spec->gpio_led, | 2358 | spec->gpio_led, |
2565 | spec->gpio_led_polarity); | 2359 | spec->gpio_led_polarity); |
@@ -2574,20 +2368,14 @@ static const struct hda_fixup stac92hd71bxx_fixups[] = { | |||
2574 | [STAC_DELL_M4_1] = { | 2368 | [STAC_DELL_M4_1] = { |
2575 | .type = HDA_FIXUP_PINS, | 2369 | .type = HDA_FIXUP_PINS, |
2576 | .v.pins = dell_m4_1_pin_configs, | 2370 | .v.pins = dell_m4_1_pin_configs, |
2577 | .chained = true, | ||
2578 | .chain_id = STAC_92HD71BXX_NO_SMUX, | ||
2579 | }, | 2371 | }, |
2580 | [STAC_DELL_M4_2] = { | 2372 | [STAC_DELL_M4_2] = { |
2581 | .type = HDA_FIXUP_PINS, | 2373 | .type = HDA_FIXUP_PINS, |
2582 | .v.pins = dell_m4_2_pin_configs, | 2374 | .v.pins = dell_m4_2_pin_configs, |
2583 | .chained = true, | ||
2584 | .chain_id = STAC_92HD71BXX_NO_DMIC, | ||
2585 | }, | 2375 | }, |
2586 | [STAC_DELL_M4_3] = { | 2376 | [STAC_DELL_M4_3] = { |
2587 | .type = HDA_FIXUP_PINS, | 2377 | .type = HDA_FIXUP_PINS, |
2588 | .v.pins = dell_m4_3_pin_configs, | 2378 | .v.pins = dell_m4_3_pin_configs, |
2589 | .chained = true, | ||
2590 | .chain_id = STAC_92HD71BXX_NO_SMUX, | ||
2591 | }, | 2379 | }, |
2592 | [STAC_HP_M4] = { | 2380 | [STAC_HP_M4] = { |
2593 | .type = HDA_FIXUP_FUNC, | 2381 | .type = HDA_FIXUP_FUNC, |
@@ -2613,20 +2401,6 @@ static const struct hda_fixup stac92hd71bxx_fixups[] = { | |||
2613 | .chained = true, | 2401 | .chained = true, |
2614 | .chain_id = STAC_92HD71BXX_HP, | 2402 | .chain_id = STAC_92HD71BXX_HP, |
2615 | }, | 2403 | }, |
2616 | [STAC_HP_DV4_1222NR] = { | ||
2617 | .type = HDA_FIXUP_FUNC, | ||
2618 | .v.func = stac92hd71bxx_fixup_hp_dv4_1222nr, | ||
2619 | .chained = true, | ||
2620 | .chain_id = STAC_HP_DV4, | ||
2621 | }, | ||
2622 | [STAC_92HD71BXX_NO_DMIC] = { | ||
2623 | .type = HDA_FIXUP_FUNC, | ||
2624 | .v.func = stac92hd71bxx_fixup_no_dmic, | ||
2625 | }, | ||
2626 | [STAC_92HD71BXX_NO_SMUX] = { | ||
2627 | .type = HDA_FIXUP_FUNC, | ||
2628 | .v.func = stac92hd71bxx_fixup_no_smux, | ||
2629 | }, | ||
2630 | [STAC_92HD71BXX_HP] = { | 2404 | [STAC_92HD71BXX_HP] = { |
2631 | .type = HDA_FIXUP_FUNC, | 2405 | .type = HDA_FIXUP_FUNC, |
2632 | .v.func = stac92hd71bxx_fixup_hp, | 2406 | .v.func = stac92hd71bxx_fixup_hp, |
@@ -2642,7 +2416,7 @@ static const struct hda_model_fixup stac92hd71bxx_models[] = { | |||
2642 | { .id = STAC_HP_DV4, .name = "hp-dv4" }, | 2416 | { .id = STAC_HP_DV4, .name = "hp-dv4" }, |
2643 | { .id = STAC_HP_DV5, .name = "hp-dv5" }, | 2417 | { .id = STAC_HP_DV5, .name = "hp-dv5" }, |
2644 | { .id = STAC_HP_HDX, .name = "hp-hdx" }, | 2418 | { .id = STAC_HP_HDX, .name = "hp-hdx" }, |
2645 | { .id = STAC_HP_DV4_1222NR, .name = "hp-dv4-1222nr" }, | 2419 | { .id = STAC_HP_DV4, .name = "hp-dv4-1222nr" }, |
2646 | {} | 2420 | {} |
2647 | }; | 2421 | }; |
2648 | 2422 | ||
@@ -2652,8 +2426,6 @@ static const struct snd_pci_quirk stac92hd71bxx_fixup_tbl[] = { | |||
2652 | "DFI LanParty", STAC_92HD71BXX_REF), | 2426 | "DFI LanParty", STAC_92HD71BXX_REF), |
2653 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 2427 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
2654 | "DFI LanParty", STAC_92HD71BXX_REF), | 2428 | "DFI LanParty", STAC_92HD71BXX_REF), |
2655 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fb, | ||
2656 | "HP dv4-1222nr", STAC_HP_DV4_1222NR), | ||
2657 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, | 2429 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, |
2658 | "HP", STAC_HP_DV5), | 2430 | "HP", STAC_HP_DV5), |
2659 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, | 2431 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, |
@@ -3234,11 +3006,9 @@ static const struct hda_pintbl dell_3st_pin_configs[] = { | |||
3234 | static void stac927x_fixup_ref_no_jd(struct hda_codec *codec, | 3006 | static void stac927x_fixup_ref_no_jd(struct hda_codec *codec, |
3235 | const struct hda_fixup *fix, int action) | 3007 | const struct hda_fixup *fix, int action) |
3236 | { | 3008 | { |
3237 | struct sigmatel_spec *spec = codec->spec; | ||
3238 | |||
3239 | /* no jack detecion for ref-no-jd model */ | 3009 | /* no jack detecion for ref-no-jd model */ |
3240 | if (action == HDA_FIXUP_ACT_PROBE) | 3010 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
3241 | spec->hp_detect = 0; | 3011 | codec->no_jack_detect = 1; |
3242 | } | 3012 | } |
3243 | 3013 | ||
3244 | static void stac927x_fixup_ref(struct hda_codec *codec, | 3014 | static void stac927x_fixup_ref(struct hda_codec *codec, |
@@ -3266,13 +3036,9 @@ static void stac927x_fixup_dell_dmic(struct hda_codec *codec, | |||
3266 | spec->eapd_mask = spec->gpio_mask = 0x04; | 3036 | spec->eapd_mask = spec->gpio_mask = 0x04; |
3267 | spec->gpio_dir = spec->gpio_data = 0x04; | 3037 | spec->gpio_dir = spec->gpio_data = 0x04; |
3268 | } | 3038 | } |
3269 | spec->dmic_nids = stac927x_dmic_nids; | ||
3270 | spec->num_dmics = STAC927X_NUM_DMICS; | ||
3271 | 3039 | ||
3272 | snd_hda_add_verbs(codec, dell_3st_core_init); | 3040 | snd_hda_add_verbs(codec, dell_3st_core_init); |
3273 | spec->volknob_init = 1; | 3041 | spec->volknob_init = 1; |
3274 | spec->dmux_nids = stac927x_dmux_nids; | ||
3275 | spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); | ||
3276 | } | 3042 | } |
3277 | 3043 | ||
3278 | static void stac927x_fixup_volknob(struct hda_codec *codec, | 3044 | static void stac927x_fixup_volknob(struct hda_codec *codec, |
@@ -3511,18 +3277,20 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, | |||
3511 | const struct hda_fixup *fix, int action) | 3277 | const struct hda_fixup *fix, int action) |
3512 | { | 3278 | { |
3513 | struct sigmatel_spec *spec = codec->spec; | 3279 | struct sigmatel_spec *spec = codec->spec; |
3514 | int err; | 3280 | struct hda_jack_tbl *jack; |
3515 | 3281 | ||
3516 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 3282 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
3517 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); | 3283 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); |
3518 | 3284 | ||
3519 | /* Enable unsol response for GPIO4/Dock HP connection */ | 3285 | /* Enable unsol response for GPIO4/Dock HP connection */ |
3520 | err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01); | ||
3521 | if (err < 0) | ||
3522 | return; | ||
3523 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 3286 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
3524 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 3287 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
3525 | snd_hda_jack_detect_enable(codec, codec->afg, 0); | 3288 | snd_hda_jack_detect_enable_callback(codec, codec->afg, |
3289 | STAC_VREF_EVENT, | ||
3290 | stac_vref_event); | ||
3291 | jack = snd_hda_jack_tbl_get(codec, codec->afg); | ||
3292 | if (jack) | ||
3293 | jack->private_data = 0x01; | ||
3526 | 3294 | ||
3527 | spec->gpio_dir = 0x0b; | 3295 | spec->gpio_dir = 0x0b; |
3528 | spec->eapd_mask = 0x01; | 3296 | spec->eapd_mask = 0x01; |
@@ -3624,1625 +3392,34 @@ static const struct snd_pci_quirk stac9205_fixup_tbl[] = { | |||
3624 | {} /* terminator */ | 3392 | {} /* terminator */ |
3625 | }; | 3393 | }; |
3626 | 3394 | ||
3627 | /* | 3395 | static int stac_parse_auto_config(struct hda_codec *codec) |
3628 | * Analog playback callbacks | ||
3629 | */ | ||
3630 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
3631 | struct hda_codec *codec, | ||
3632 | struct snd_pcm_substream *substream) | ||
3633 | { | ||
3634 | struct sigmatel_spec *spec = codec->spec; | ||
3635 | if (spec->stream_delay) | ||
3636 | msleep(spec->stream_delay); | ||
3637 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
3638 | hinfo); | ||
3639 | } | ||
3640 | |||
3641 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3642 | struct hda_codec *codec, | ||
3643 | unsigned int stream_tag, | ||
3644 | unsigned int format, | ||
3645 | struct snd_pcm_substream *substream) | ||
3646 | { | ||
3647 | struct sigmatel_spec *spec = codec->spec; | ||
3648 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream); | ||
3649 | } | ||
3650 | |||
3651 | static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3652 | struct hda_codec *codec, | ||
3653 | struct snd_pcm_substream *substream) | ||
3654 | { | 3396 | { |
3655 | struct sigmatel_spec *spec = codec->spec; | 3397 | struct sigmatel_spec *spec = codec->spec; |
3656 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
3657 | } | ||
3658 | |||
3659 | /* | ||
3660 | * Digital playback callbacks | ||
3661 | */ | ||
3662 | static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
3663 | struct hda_codec *codec, | ||
3664 | struct snd_pcm_substream *substream) | ||
3665 | { | ||
3666 | struct sigmatel_spec *spec = codec->spec; | ||
3667 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
3668 | } | ||
3669 | |||
3670 | static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
3671 | struct hda_codec *codec, | ||
3672 | struct snd_pcm_substream *substream) | ||
3673 | { | ||
3674 | struct sigmatel_spec *spec = codec->spec; | ||
3675 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
3676 | } | ||
3677 | |||
3678 | static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3679 | struct hda_codec *codec, | ||
3680 | unsigned int stream_tag, | ||
3681 | unsigned int format, | ||
3682 | struct snd_pcm_substream *substream) | ||
3683 | { | ||
3684 | struct sigmatel_spec *spec = codec->spec; | ||
3685 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
3686 | stream_tag, format, substream); | ||
3687 | } | ||
3688 | |||
3689 | static int stac92xx_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3690 | struct hda_codec *codec, | ||
3691 | struct snd_pcm_substream *substream) | ||
3692 | { | ||
3693 | struct sigmatel_spec *spec = codec->spec; | ||
3694 | return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
3695 | } | ||
3696 | |||
3697 | |||
3698 | /* | ||
3699 | * Analog capture callbacks | ||
3700 | */ | ||
3701 | static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3702 | struct hda_codec *codec, | ||
3703 | unsigned int stream_tag, | ||
3704 | unsigned int format, | ||
3705 | struct snd_pcm_substream *substream) | ||
3706 | { | ||
3707 | struct sigmatel_spec *spec = codec->spec; | ||
3708 | hda_nid_t nid = spec->adc_nids[substream->number]; | ||
3709 | |||
3710 | if (spec->powerdown_adcs) { | ||
3711 | msleep(40); | ||
3712 | snd_hda_codec_write(codec, nid, 0, | ||
3713 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
3714 | } | ||
3715 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | ||
3716 | return 0; | ||
3717 | } | ||
3718 | |||
3719 | static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3720 | struct hda_codec *codec, | ||
3721 | struct snd_pcm_substream *substream) | ||
3722 | { | ||
3723 | struct sigmatel_spec *spec = codec->spec; | ||
3724 | hda_nid_t nid = spec->adc_nids[substream->number]; | ||
3725 | |||
3726 | snd_hda_codec_cleanup_stream(codec, nid); | ||
3727 | if (spec->powerdown_adcs) | ||
3728 | snd_hda_codec_write(codec, nid, 0, | ||
3729 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
3730 | return 0; | ||
3731 | } | ||
3732 | |||
3733 | static const struct hda_pcm_stream stac92xx_pcm_digital_playback = { | ||
3734 | .substreams = 1, | ||
3735 | .channels_min = 2, | ||
3736 | .channels_max = 2, | ||
3737 | /* NID is set in stac92xx_build_pcms */ | ||
3738 | .ops = { | ||
3739 | .open = stac92xx_dig_playback_pcm_open, | ||
3740 | .close = stac92xx_dig_playback_pcm_close, | ||
3741 | .prepare = stac92xx_dig_playback_pcm_prepare, | ||
3742 | .cleanup = stac92xx_dig_playback_pcm_cleanup | ||
3743 | }, | ||
3744 | }; | ||
3745 | |||
3746 | static const struct hda_pcm_stream stac92xx_pcm_digital_capture = { | ||
3747 | .substreams = 1, | ||
3748 | .channels_min = 2, | ||
3749 | .channels_max = 2, | ||
3750 | /* NID is set in stac92xx_build_pcms */ | ||
3751 | }; | ||
3752 | |||
3753 | static const struct hda_pcm_stream stac92xx_pcm_analog_playback = { | ||
3754 | .substreams = 1, | ||
3755 | .channels_min = 2, | ||
3756 | .channels_max = 8, | ||
3757 | .nid = 0x02, /* NID to query formats and rates */ | ||
3758 | .ops = { | ||
3759 | .open = stac92xx_playback_pcm_open, | ||
3760 | .prepare = stac92xx_playback_pcm_prepare, | ||
3761 | .cleanup = stac92xx_playback_pcm_cleanup | ||
3762 | }, | ||
3763 | }; | ||
3764 | |||
3765 | static const struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { | ||
3766 | .substreams = 1, | ||
3767 | .channels_min = 2, | ||
3768 | .channels_max = 2, | ||
3769 | .nid = 0x06, /* NID to query formats and rates */ | ||
3770 | .ops = { | ||
3771 | .open = stac92xx_playback_pcm_open, | ||
3772 | .prepare = stac92xx_playback_pcm_prepare, | ||
3773 | .cleanup = stac92xx_playback_pcm_cleanup | ||
3774 | }, | ||
3775 | }; | ||
3776 | |||
3777 | static const struct hda_pcm_stream stac92xx_pcm_analog_capture = { | ||
3778 | .channels_min = 2, | ||
3779 | .channels_max = 2, | ||
3780 | /* NID + .substreams is set in stac92xx_build_pcms */ | ||
3781 | .ops = { | ||
3782 | .prepare = stac92xx_capture_pcm_prepare, | ||
3783 | .cleanup = stac92xx_capture_pcm_cleanup | ||
3784 | }, | ||
3785 | }; | ||
3786 | |||
3787 | static int stac92xx_build_pcms(struct hda_codec *codec) | ||
3788 | { | ||
3789 | struct sigmatel_spec *spec = codec->spec; | ||
3790 | struct hda_pcm *info = spec->pcm_rec; | ||
3791 | |||
3792 | codec->num_pcms = 1; | ||
3793 | codec->pcm_info = info; | ||
3794 | |||
3795 | info->name = "STAC92xx Analog"; | ||
3796 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | ||
3797 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
3798 | spec->multiout.dac_nids[0]; | ||
3799 | if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && | ||
3800 | spec->autocfg.line_outs == 2) | ||
3801 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = | ||
3802 | snd_pcm_2_1_chmaps; | ||
3803 | |||
3804 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | ||
3805 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
3806 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; | ||
3807 | |||
3808 | if (spec->alt_switch) { | ||
3809 | codec->num_pcms++; | ||
3810 | info++; | ||
3811 | info->name = "STAC92xx Analog Alt"; | ||
3812 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback; | ||
3813 | } | ||
3814 | |||
3815 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | ||
3816 | codec->num_pcms++; | ||
3817 | info++; | ||
3818 | info->name = "STAC92xx Digital"; | ||
3819 | info->pcm_type = spec->autocfg.dig_out_type[0]; | ||
3820 | if (spec->multiout.dig_out_nid) { | ||
3821 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | ||
3822 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
3823 | } | ||
3824 | if (spec->dig_in_nid) { | ||
3825 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture; | ||
3826 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | ||
3827 | } | ||
3828 | } | ||
3829 | |||
3830 | return 0; | ||
3831 | } | ||
3832 | |||
3833 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | ||
3834 | |||
3835 | { | ||
3836 | snd_hda_set_pin_ctl_cache(codec, nid, pin_type); | ||
3837 | } | ||
3838 | |||
3839 | #define stac92xx_hp_switch_info snd_ctl_boolean_mono_info | ||
3840 | |||
3841 | static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, | ||
3842 | struct snd_ctl_elem_value *ucontrol) | ||
3843 | { | ||
3844 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3845 | struct sigmatel_spec *spec = codec->spec; | ||
3846 | |||
3847 | ucontrol->value.integer.value[0] = !!spec->hp_switch; | ||
3848 | return 0; | ||
3849 | } | ||
3850 | |||
3851 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid); | ||
3852 | |||
3853 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | ||
3854 | struct snd_ctl_elem_value *ucontrol) | ||
3855 | { | ||
3856 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3857 | struct sigmatel_spec *spec = codec->spec; | ||
3858 | int nid = kcontrol->private_value; | ||
3859 | |||
3860 | spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0; | ||
3861 | |||
3862 | /* check to be sure that the ports are up to date with | ||
3863 | * switch changes | ||
3864 | */ | ||
3865 | stac_issue_unsol_event(codec, nid); | ||
3866 | |||
3867 | return 1; | ||
3868 | } | ||
3869 | |||
3870 | static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol, | ||
3871 | struct snd_ctl_elem_info *uinfo) | ||
3872 | { | ||
3873 | int i; | ||
3874 | static const char * const texts[] = { | ||
3875 | "Mic In", "Line In", "Line Out" | ||
3876 | }; | ||
3877 | |||
3878 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3879 | struct sigmatel_spec *spec = codec->spec; | ||
3880 | hda_nid_t nid = kcontrol->private_value; | ||
3881 | |||
3882 | if (nid == spec->mic_switch || nid == spec->line_switch) | ||
3883 | i = 3; | ||
3884 | else | ||
3885 | i = 2; | ||
3886 | |||
3887 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3888 | uinfo->value.enumerated.items = i; | ||
3889 | uinfo->count = 1; | ||
3890 | if (uinfo->value.enumerated.item >= i) | ||
3891 | uinfo->value.enumerated.item = i-1; | ||
3892 | strcpy(uinfo->value.enumerated.name, | ||
3893 | texts[uinfo->value.enumerated.item]); | ||
3894 | |||
3895 | return 0; | ||
3896 | } | ||
3897 | |||
3898 | static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol, | ||
3899 | struct snd_ctl_elem_value *ucontrol) | ||
3900 | { | ||
3901 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3902 | hda_nid_t nid = kcontrol->private_value; | ||
3903 | unsigned int vref = stac92xx_vref_get(codec, nid); | ||
3904 | |||
3905 | if (vref == snd_hda_get_default_vref(codec, nid)) | ||
3906 | ucontrol->value.enumerated.item[0] = 0; | ||
3907 | else if (vref == AC_PINCTL_VREF_GRD) | ||
3908 | ucontrol->value.enumerated.item[0] = 1; | ||
3909 | else if (vref == AC_PINCTL_VREF_HIZ) | ||
3910 | ucontrol->value.enumerated.item[0] = 2; | ||
3911 | |||
3912 | return 0; | ||
3913 | } | ||
3914 | |||
3915 | static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol, | ||
3916 | struct snd_ctl_elem_value *ucontrol) | ||
3917 | { | ||
3918 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3919 | unsigned int new_vref = 0; | ||
3920 | int error; | ||
3921 | hda_nid_t nid = kcontrol->private_value; | ||
3922 | |||
3923 | if (ucontrol->value.enumerated.item[0] == 0) | ||
3924 | new_vref = snd_hda_get_default_vref(codec, nid); | ||
3925 | else if (ucontrol->value.enumerated.item[0] == 1) | ||
3926 | new_vref = AC_PINCTL_VREF_GRD; | ||
3927 | else if (ucontrol->value.enumerated.item[0] == 2) | ||
3928 | new_vref = AC_PINCTL_VREF_HIZ; | ||
3929 | else | ||
3930 | return 0; | ||
3931 | |||
3932 | if (new_vref != stac92xx_vref_get(codec, nid)) { | ||
3933 | error = stac92xx_vref_set(codec, nid, new_vref); | ||
3934 | return error; | ||
3935 | } | ||
3936 | |||
3937 | return 0; | ||
3938 | } | ||
3939 | |||
3940 | static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, | ||
3941 | struct snd_ctl_elem_info *uinfo) | ||
3942 | { | ||
3943 | char *texts[2]; | ||
3944 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3945 | struct sigmatel_spec *spec = codec->spec; | ||
3946 | |||
3947 | if (kcontrol->private_value == spec->line_switch) | ||
3948 | texts[0] = "Line In"; | ||
3949 | else | ||
3950 | texts[0] = "Mic In"; | ||
3951 | texts[1] = "Line Out"; | ||
3952 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3953 | uinfo->value.enumerated.items = 2; | ||
3954 | uinfo->count = 1; | ||
3955 | |||
3956 | if (uinfo->value.enumerated.item >= 2) | ||
3957 | uinfo->value.enumerated.item = 1; | ||
3958 | strcpy(uinfo->value.enumerated.name, | ||
3959 | texts[uinfo->value.enumerated.item]); | ||
3960 | |||
3961 | return 0; | ||
3962 | } | ||
3963 | |||
3964 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
3965 | { | ||
3966 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3967 | struct sigmatel_spec *spec = codec->spec; | ||
3968 | hda_nid_t nid = kcontrol->private_value; | ||
3969 | int io_idx = (nid == spec->mic_switch) ? 1 : 0; | ||
3970 | |||
3971 | ucontrol->value.enumerated.item[0] = spec->io_switch[io_idx]; | ||
3972 | return 0; | ||
3973 | } | ||
3974 | |||
3975 | static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
3976 | { | ||
3977 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3978 | struct sigmatel_spec *spec = codec->spec; | ||
3979 | hda_nid_t nid = kcontrol->private_value; | ||
3980 | int io_idx = (nid == spec->mic_switch) ? 1 : 0; | ||
3981 | unsigned short val = !!ucontrol->value.enumerated.item[0]; | ||
3982 | |||
3983 | spec->io_switch[io_idx] = val; | ||
3984 | |||
3985 | if (val) | ||
3986 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
3987 | else { | ||
3988 | unsigned int pinctl = AC_PINCTL_IN_EN; | ||
3989 | if (io_idx) /* set VREF for mic */ | ||
3990 | pinctl |= snd_hda_get_default_vref(codec, nid); | ||
3991 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
3992 | } | ||
3993 | |||
3994 | /* check the auto-mute again: we need to mute/unmute the speaker | ||
3995 | * appropriately according to the pin direction | ||
3996 | */ | ||
3997 | if (spec->hp_detect) | ||
3998 | stac_issue_unsol_event(codec, nid); | ||
3999 | |||
4000 | return 1; | ||
4001 | } | ||
4002 | |||
4003 | #define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info | ||
4004 | |||
4005 | static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, | ||
4006 | struct snd_ctl_elem_value *ucontrol) | ||
4007 | { | ||
4008 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4009 | struct sigmatel_spec *spec = codec->spec; | ||
4010 | |||
4011 | ucontrol->value.integer.value[0] = spec->clfe_swap; | ||
4012 | return 0; | ||
4013 | } | ||
4014 | |||
4015 | static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | ||
4016 | struct snd_ctl_elem_value *ucontrol) | ||
4017 | { | ||
4018 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4019 | struct sigmatel_spec *spec = codec->spec; | ||
4020 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
4021 | unsigned int val = !!ucontrol->value.integer.value[0]; | ||
4022 | |||
4023 | if (spec->clfe_swap == val) | ||
4024 | return 0; | ||
4025 | |||
4026 | spec->clfe_swap = val; | ||
4027 | |||
4028 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
4029 | spec->clfe_swap ? 0x4 : 0x0); | ||
4030 | |||
4031 | return 1; | ||
4032 | } | ||
4033 | |||
4034 | #define STAC_CODEC_HP_SWITCH(xname) \ | ||
4035 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4036 | .name = xname, \ | ||
4037 | .index = 0, \ | ||
4038 | .info = stac92xx_hp_switch_info, \ | ||
4039 | .get = stac92xx_hp_switch_get, \ | ||
4040 | .put = stac92xx_hp_switch_put, \ | ||
4041 | } | ||
4042 | |||
4043 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ | ||
4044 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4045 | .name = xname, \ | ||
4046 | .index = 0, \ | ||
4047 | .info = stac92xx_io_switch_info, \ | ||
4048 | .get = stac92xx_io_switch_get, \ | ||
4049 | .put = stac92xx_io_switch_put, \ | ||
4050 | .private_value = xpval, \ | ||
4051 | } | ||
4052 | |||
4053 | #define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ | ||
4054 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4055 | .name = xname, \ | ||
4056 | .index = 0, \ | ||
4057 | .info = stac92xx_clfe_switch_info, \ | ||
4058 | .get = stac92xx_clfe_switch_get, \ | ||
4059 | .put = stac92xx_clfe_switch_put, \ | ||
4060 | .private_value = xpval, \ | ||
4061 | } | ||
4062 | |||
4063 | enum { | ||
4064 | STAC_CTL_WIDGET_VOL, | ||
4065 | STAC_CTL_WIDGET_MUTE, | ||
4066 | STAC_CTL_WIDGET_MUTE_BEEP, | ||
4067 | STAC_CTL_WIDGET_MONO_MUX, | ||
4068 | STAC_CTL_WIDGET_HP_SWITCH, | ||
4069 | STAC_CTL_WIDGET_IO_SWITCH, | ||
4070 | STAC_CTL_WIDGET_CLFE_SWITCH, | ||
4071 | STAC_CTL_WIDGET_DC_BIAS | ||
4072 | }; | ||
4073 | |||
4074 | static const struct snd_kcontrol_new stac92xx_control_templates[] = { | ||
4075 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | ||
4076 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | ||
4077 | HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0), | ||
4078 | STAC_MONO_MUX, | ||
4079 | STAC_CODEC_HP_SWITCH(NULL), | ||
4080 | STAC_CODEC_IO_SWITCH(NULL, 0), | ||
4081 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | ||
4082 | DC_BIAS(NULL, 0, 0), | ||
4083 | }; | ||
4084 | |||
4085 | /* add dynamic controls */ | ||
4086 | static struct snd_kcontrol_new * | ||
4087 | stac_control_new(struct sigmatel_spec *spec, | ||
4088 | const struct snd_kcontrol_new *ktemp, | ||
4089 | const char *name, | ||
4090 | unsigned int subdev) | ||
4091 | { | ||
4092 | struct snd_kcontrol_new *knew; | ||
4093 | |||
4094 | knew = snd_array_new(&spec->kctls); | ||
4095 | if (!knew) | ||
4096 | return NULL; | ||
4097 | *knew = *ktemp; | ||
4098 | knew->name = kstrdup(name, GFP_KERNEL); | ||
4099 | if (!knew->name) { | ||
4100 | /* roolback */ | ||
4101 | memset(knew, 0, sizeof(*knew)); | ||
4102 | spec->kctls.alloced--; | ||
4103 | return NULL; | ||
4104 | } | ||
4105 | knew->subdevice = subdev; | ||
4106 | return knew; | ||
4107 | } | ||
4108 | |||
4109 | static struct snd_kcontrol_new * | ||
4110 | add_control_temp(struct sigmatel_spec *spec, | ||
4111 | const struct snd_kcontrol_new *ktemp, | ||
4112 | int idx, const char *name, | ||
4113 | unsigned long val) | ||
4114 | { | ||
4115 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | ||
4116 | HDA_SUBDEV_AMP_FLAG); | ||
4117 | if (!knew) | ||
4118 | return NULL; | ||
4119 | knew->index = idx; | ||
4120 | knew->private_value = val; | ||
4121 | return knew; | ||
4122 | } | ||
4123 | |||
4124 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | ||
4125 | const struct snd_kcontrol_new *ktemp, | ||
4126 | int idx, const char *name, | ||
4127 | unsigned long val) | ||
4128 | { | ||
4129 | return add_control_temp(spec, ktemp, idx, name, val) ? 0 : -ENOMEM; | ||
4130 | } | ||
4131 | |||
4132 | static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec, | ||
4133 | int type, int idx, const char *name, | ||
4134 | unsigned long val) | ||
4135 | { | ||
4136 | return stac92xx_add_control_temp(spec, | ||
4137 | &stac92xx_control_templates[type], | ||
4138 | idx, name, val); | ||
4139 | } | ||
4140 | |||
4141 | |||
4142 | /* add dynamic controls */ | ||
4143 | static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, | ||
4144 | const char *name, unsigned long val) | ||
4145 | { | ||
4146 | return stac92xx_add_control_idx(spec, type, 0, name, val); | ||
4147 | } | ||
4148 | |||
4149 | static const struct snd_kcontrol_new stac_input_src_temp = { | ||
4150 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4151 | .name = "Input Source", | ||
4152 | .info = stac92xx_mux_enum_info, | ||
4153 | .get = stac92xx_mux_enum_get, | ||
4154 | .put = stac92xx_mux_enum_put, | ||
4155 | }; | ||
4156 | |||
4157 | static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | ||
4158 | hda_nid_t nid, int idx) | ||
4159 | { | ||
4160 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4161 | int control = 0; | ||
4162 | struct sigmatel_spec *spec = codec->spec; | ||
4163 | char name[22]; | ||
4164 | |||
4165 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { | ||
4166 | if (spec->headset_jack && snd_hda_get_input_pin_attr(def_conf) | ||
4167 | != INPUT_PIN_ATTR_DOCK) | ||
4168 | return 0; | ||
4169 | if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD | ||
4170 | && nid == spec->line_switch) | ||
4171 | control = STAC_CTL_WIDGET_IO_SWITCH; | ||
4172 | else if (snd_hda_query_pin_caps(codec, nid) | ||
4173 | & (AC_PINCAP_VREF_GRD << AC_PINCAP_VREF_SHIFT)) | ||
4174 | control = STAC_CTL_WIDGET_DC_BIAS; | ||
4175 | else if (nid == spec->mic_switch) | ||
4176 | control = STAC_CTL_WIDGET_IO_SWITCH; | ||
4177 | } | ||
4178 | |||
4179 | if (control) { | ||
4180 | snd_hda_get_pin_label(codec, nid, &spec->autocfg, | ||
4181 | name, sizeof(name), NULL); | ||
4182 | return stac92xx_add_control(codec->spec, control, | ||
4183 | strcat(name, " Jack Mode"), nid); | ||
4184 | } | ||
4185 | |||
4186 | return 0; | ||
4187 | } | ||
4188 | |||
4189 | static int stac92xx_add_input_source(struct sigmatel_spec *spec) | ||
4190 | { | ||
4191 | struct snd_kcontrol_new *knew; | ||
4192 | struct hda_input_mux *imux = &spec->private_imux; | ||
4193 | |||
4194 | if (spec->auto_mic) | ||
4195 | return 0; /* no need for input source */ | ||
4196 | if (!spec->num_adcs || imux->num_items <= 1) | ||
4197 | return 0; /* no need for input source control */ | ||
4198 | knew = stac_control_new(spec, &stac_input_src_temp, | ||
4199 | stac_input_src_temp.name, 0); | ||
4200 | if (!knew) | ||
4201 | return -ENOMEM; | ||
4202 | knew->count = spec->num_adcs; | ||
4203 | return 0; | ||
4204 | } | ||
4205 | |||
4206 | /* check whether the line-input can be used as line-out */ | ||
4207 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) | ||
4208 | { | ||
4209 | struct sigmatel_spec *spec = codec->spec; | ||
4210 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
4211 | hda_nid_t nid; | ||
4212 | unsigned int pincap; | ||
4213 | int i; | ||
4214 | |||
4215 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | ||
4216 | return 0; | ||
4217 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4218 | if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) { | ||
4219 | nid = cfg->inputs[i].pin; | ||
4220 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
4221 | if (pincap & AC_PINCAP_OUT) | ||
4222 | return nid; | ||
4223 | } | ||
4224 | } | ||
4225 | return 0; | ||
4226 | } | ||
4227 | |||
4228 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); | ||
4229 | |||
4230 | /* check whether the mic-input can be used as line-out */ | ||
4231 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) | ||
4232 | { | ||
4233 | struct sigmatel_spec *spec = codec->spec; | ||
4234 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
4235 | unsigned int def_conf, pincap; | ||
4236 | int i; | ||
4237 | |||
4238 | *dac = 0; | ||
4239 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | ||
4240 | return 0; | ||
4241 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4242 | hda_nid_t nid = cfg->inputs[i].pin; | ||
4243 | if (cfg->inputs[i].type != AUTO_PIN_MIC) | ||
4244 | continue; | ||
4245 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4246 | /* some laptops have an internal analog microphone | ||
4247 | * which can't be used as a output */ | ||
4248 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { | ||
4249 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
4250 | if (pincap & AC_PINCAP_OUT) { | ||
4251 | *dac = get_unassigned_dac(codec, nid); | ||
4252 | if (*dac) | ||
4253 | return nid; | ||
4254 | } | ||
4255 | } | ||
4256 | } | ||
4257 | return 0; | ||
4258 | } | ||
4259 | |||
4260 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | ||
4261 | { | ||
4262 | int i; | ||
4263 | |||
4264 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
4265 | if (spec->multiout.dac_nids[i] == nid) | ||
4266 | return 1; | ||
4267 | } | ||
4268 | |||
4269 | return 0; | ||
4270 | } | ||
4271 | |||
4272 | static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | ||
4273 | { | ||
4274 | int i; | ||
4275 | if (is_in_dac_nids(spec, nid)) | ||
4276 | return 1; | ||
4277 | for (i = 0; i < spec->autocfg.hp_outs; i++) | ||
4278 | if (spec->hp_dacs[i] == nid) | ||
4279 | return 1; | ||
4280 | for (i = 0; i < spec->autocfg.speaker_outs; i++) | ||
4281 | if (spec->speaker_dacs[i] == nid) | ||
4282 | return 1; | ||
4283 | return 0; | ||
4284 | } | ||
4285 | |||
4286 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | ||
4287 | { | ||
4288 | struct sigmatel_spec *spec = codec->spec; | ||
4289 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
4290 | int j, conn_len; | ||
4291 | hda_nid_t conn[HDA_MAX_CONNECTIONS], fallback_dac; | ||
4292 | unsigned int wcaps, wtype; | ||
4293 | |||
4294 | conn_len = snd_hda_get_connections(codec, nid, conn, | ||
4295 | HDA_MAX_CONNECTIONS); | ||
4296 | /* 92HD88: trace back up the link of nids to find the DAC */ | ||
4297 | while (conn_len == 1 && (get_wcaps_type(get_wcaps(codec, conn[0])) | ||
4298 | != AC_WID_AUD_OUT)) { | ||
4299 | nid = conn[0]; | ||
4300 | conn_len = snd_hda_get_connections(codec, nid, conn, | ||
4301 | HDA_MAX_CONNECTIONS); | ||
4302 | } | ||
4303 | for (j = 0; j < conn_len; j++) { | ||
4304 | wcaps = get_wcaps(codec, conn[j]); | ||
4305 | wtype = get_wcaps_type(wcaps); | ||
4306 | /* we check only analog outputs */ | ||
4307 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) | ||
4308 | continue; | ||
4309 | /* if this route has a free DAC, assign it */ | ||
4310 | if (!check_all_dac_nids(spec, conn[j])) { | ||
4311 | if (conn_len > 1) { | ||
4312 | /* select this DAC in the pin's input mux */ | ||
4313 | snd_hda_codec_write_cache(codec, nid, 0, | ||
4314 | AC_VERB_SET_CONNECT_SEL, j); | ||
4315 | } | ||
4316 | return conn[j]; | ||
4317 | } | ||
4318 | } | ||
4319 | |||
4320 | /* if all DACs are already assigned, connect to the primary DAC, | ||
4321 | unless we're assigning a secondary headphone */ | ||
4322 | fallback_dac = spec->multiout.dac_nids[0]; | ||
4323 | if (spec->multiout.hp_nid) { | ||
4324 | for (j = 0; j < cfg->hp_outs; j++) | ||
4325 | if (cfg->hp_pins[j] == nid) { | ||
4326 | fallback_dac = spec->multiout.hp_nid; | ||
4327 | break; | ||
4328 | } | ||
4329 | } | ||
4330 | |||
4331 | if (conn_len > 1) { | ||
4332 | for (j = 0; j < conn_len; j++) { | ||
4333 | if (conn[j] == fallback_dac) { | ||
4334 | snd_hda_codec_write_cache(codec, nid, 0, | ||
4335 | AC_VERB_SET_CONNECT_SEL, j); | ||
4336 | break; | ||
4337 | } | ||
4338 | } | ||
4339 | } | ||
4340 | return 0; | ||
4341 | } | ||
4342 | |||
4343 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | ||
4344 | static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | ||
4345 | |||
4346 | /* | ||
4347 | * Fill in the dac_nids table from the parsed pin configuration | ||
4348 | * This function only works when every pin in line_out_pins[] | ||
4349 | * contains atleast one DAC in its connection list. Some 92xx | ||
4350 | * codecs are not connected directly to a DAC, such as the 9200 | ||
4351 | * and 9202/925x. For those, dac_nids[] must be hard-coded. | ||
4352 | */ | ||
4353 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | ||
4354 | { | ||
4355 | struct sigmatel_spec *spec = codec->spec; | ||
4356 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
4357 | int i; | ||
4358 | hda_nid_t nid, dac; | ||
4359 | |||
4360 | for (i = 0; i < cfg->line_outs; i++) { | ||
4361 | nid = cfg->line_out_pins[i]; | ||
4362 | dac = get_unassigned_dac(codec, nid); | ||
4363 | if (!dac) { | ||
4364 | if (spec->multiout.num_dacs > 0) { | ||
4365 | /* we have already working output pins, | ||
4366 | * so let's drop the broken ones again | ||
4367 | */ | ||
4368 | cfg->line_outs = spec->multiout.num_dacs; | ||
4369 | break; | ||
4370 | } | ||
4371 | /* error out, no available DAC found */ | ||
4372 | snd_printk(KERN_ERR | ||
4373 | "%s: No available DAC for pin 0x%x\n", | ||
4374 | __func__, nid); | ||
4375 | return -ENODEV; | ||
4376 | } | ||
4377 | add_spec_dacs(spec, dac); | ||
4378 | } | ||
4379 | |||
4380 | for (i = 0; i < cfg->hp_outs; i++) { | ||
4381 | nid = cfg->hp_pins[i]; | ||
4382 | dac = get_unassigned_dac(codec, nid); | ||
4383 | if (dac) { | ||
4384 | if (!spec->multiout.hp_nid) | ||
4385 | spec->multiout.hp_nid = dac; | ||
4386 | else | ||
4387 | add_spec_extra_dacs(spec, dac); | ||
4388 | } | ||
4389 | spec->hp_dacs[i] = dac; | ||
4390 | } | ||
4391 | |||
4392 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
4393 | nid = cfg->speaker_pins[i]; | ||
4394 | dac = get_unassigned_dac(codec, nid); | ||
4395 | if (dac) | ||
4396 | add_spec_extra_dacs(spec, dac); | ||
4397 | spec->speaker_dacs[i] = dac; | ||
4398 | } | ||
4399 | |||
4400 | /* add line-in as output */ | ||
4401 | nid = check_line_out_switch(codec); | ||
4402 | if (nid) { | ||
4403 | dac = get_unassigned_dac(codec, nid); | ||
4404 | if (dac) { | ||
4405 | snd_printdd("STAC: Add line-in 0x%x as output %d\n", | ||
4406 | nid, cfg->line_outs); | ||
4407 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
4408 | cfg->line_outs++; | ||
4409 | spec->line_switch = nid; | ||
4410 | add_spec_dacs(spec, dac); | ||
4411 | } | ||
4412 | } | ||
4413 | /* add mic as output */ | ||
4414 | nid = check_mic_out_switch(codec, &dac); | ||
4415 | if (nid && dac) { | ||
4416 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | ||
4417 | nid, cfg->line_outs); | ||
4418 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
4419 | cfg->line_outs++; | ||
4420 | spec->mic_switch = nid; | ||
4421 | add_spec_dacs(spec, dac); | ||
4422 | } | ||
4423 | |||
4424 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
4425 | spec->multiout.num_dacs, | ||
4426 | spec->multiout.dac_nids[0], | ||
4427 | spec->multiout.dac_nids[1], | ||
4428 | spec->multiout.dac_nids[2], | ||
4429 | spec->multiout.dac_nids[3], | ||
4430 | spec->multiout.dac_nids[4]); | ||
4431 | |||
4432 | return 0; | ||
4433 | } | ||
4434 | |||
4435 | /* create volume control/switch for the given prefx type */ | ||
4436 | static int create_controls_idx(struct hda_codec *codec, const char *pfx, | ||
4437 | int idx, hda_nid_t nid, int chs) | ||
4438 | { | ||
4439 | struct sigmatel_spec *spec = codec->spec; | ||
4440 | char name[32]; | ||
4441 | int err; | 3398 | int err; |
4442 | 3399 | ||
4443 | if (!spec->check_volume_offset) { | 3400 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); |
4444 | unsigned int caps, step, nums, db_scale; | ||
4445 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | ||
4446 | step = (caps & AC_AMPCAP_STEP_SIZE) >> | ||
4447 | AC_AMPCAP_STEP_SIZE_SHIFT; | ||
4448 | step = (step + 1) * 25; /* in .01dB unit */ | ||
4449 | nums = (caps & AC_AMPCAP_NUM_STEPS) >> | ||
4450 | AC_AMPCAP_NUM_STEPS_SHIFT; | ||
4451 | db_scale = nums * step; | ||
4452 | /* if dB scale is over -64dB, and finer enough, | ||
4453 | * let's reduce it to half | ||
4454 | */ | ||
4455 | if (db_scale > 6400 && nums >= 0x1f) | ||
4456 | spec->volume_offset = nums / 2; | ||
4457 | spec->check_volume_offset = 1; | ||
4458 | } | ||
4459 | |||
4460 | sprintf(name, "%s Playback Volume", pfx); | ||
4461 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name, | ||
4462 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT, | ||
4463 | spec->volume_offset)); | ||
4464 | if (err < 0) | 3401 | if (err < 0) |
4465 | return err; | 3402 | return err; |
4466 | sprintf(name, "%s Playback Switch", pfx); | ||
4467 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name, | ||
4468 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
4469 | if (err < 0) | ||
4470 | return err; | ||
4471 | return 0; | ||
4472 | } | ||
4473 | |||
4474 | #define create_controls(codec, pfx, nid, chs) \ | ||
4475 | create_controls_idx(codec, pfx, 0, nid, chs) | ||
4476 | |||
4477 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | ||
4478 | { | ||
4479 | if (spec->multiout.num_dacs > 4) { | ||
4480 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | ||
4481 | return 1; | ||
4482 | } else { | ||
4483 | snd_BUG_ON(spec->multiout.dac_nids != spec->dac_nids); | ||
4484 | spec->dac_nids[spec->multiout.num_dacs] = nid; | ||
4485 | spec->multiout.num_dacs++; | ||
4486 | } | ||
4487 | return 0; | ||
4488 | } | ||
4489 | |||
4490 | static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | ||
4491 | { | ||
4492 | int i; | ||
4493 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) { | ||
4494 | if (!spec->multiout.extra_out_nid[i]) { | ||
4495 | spec->multiout.extra_out_nid[i] = nid; | ||
4496 | return 0; | ||
4497 | } | ||
4498 | } | ||
4499 | printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid); | ||
4500 | return 1; | ||
4501 | } | ||
4502 | |||
4503 | /* Create output controls | ||
4504 | * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT) | ||
4505 | */ | ||
4506 | static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | ||
4507 | const hda_nid_t *pins, | ||
4508 | const hda_nid_t *dac_nids, | ||
4509 | int type) | ||
4510 | { | ||
4511 | struct sigmatel_spec *spec = codec->spec; | ||
4512 | static const char * const chname[4] = { | ||
4513 | "Front", "Surround", NULL /*CLFE*/, "Side" | ||
4514 | }; | ||
4515 | hda_nid_t nid; | ||
4516 | int i, err; | ||
4517 | unsigned int wid_caps; | ||
4518 | |||
4519 | for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { | ||
4520 | if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { | ||
4521 | if (is_jack_detectable(codec, pins[i])) | ||
4522 | spec->hp_detect = 1; | ||
4523 | } | ||
4524 | nid = dac_nids[i]; | ||
4525 | if (!nid) | ||
4526 | continue; | ||
4527 | if (type != AUTO_PIN_HP_OUT && i == 2) { | ||
4528 | /* Center/LFE */ | ||
4529 | err = create_controls(codec, "Center", nid, 1); | ||
4530 | if (err < 0) | ||
4531 | return err; | ||
4532 | err = create_controls(codec, "LFE", nid, 2); | ||
4533 | if (err < 0) | ||
4534 | return err; | ||
4535 | |||
4536 | wid_caps = get_wcaps(codec, nid); | ||
4537 | |||
4538 | if (wid_caps & AC_WCAP_LR_SWAP) { | ||
4539 | err = stac92xx_add_control(spec, | ||
4540 | STAC_CTL_WIDGET_CLFE_SWITCH, | ||
4541 | "Swap Center/LFE Playback Switch", nid); | ||
4542 | |||
4543 | if (err < 0) | ||
4544 | return err; | ||
4545 | } | ||
4546 | |||
4547 | } else { | ||
4548 | const char *name; | ||
4549 | int idx; | ||
4550 | switch (type) { | ||
4551 | case AUTO_PIN_HP_OUT: | ||
4552 | name = "Headphone"; | ||
4553 | idx = i; | ||
4554 | break; | ||
4555 | case AUTO_PIN_SPEAKER_OUT: | ||
4556 | if (num_outs <= 2) { | ||
4557 | name = i ? "Bass Speaker" : "Speaker"; | ||
4558 | idx = 0; | ||
4559 | break; | ||
4560 | } | ||
4561 | /* Fall through in case of multi speaker outs */ | ||
4562 | default: | ||
4563 | name = chname[i]; | ||
4564 | idx = 0; | ||
4565 | break; | ||
4566 | } | ||
4567 | err = create_controls_idx(codec, name, idx, nid, 3); | ||
4568 | if (err < 0) | ||
4569 | return err; | ||
4570 | } | ||
4571 | } | ||
4572 | return 0; | ||
4573 | } | ||
4574 | 3403 | ||
4575 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | 3404 | /* add hooks */ |
4576 | unsigned int dir_mask, unsigned int data); | 3405 | spec->gen.pcm_playback_hook = stac_playback_pcm_hook; |
3406 | spec->gen.pcm_capture_hook = stac_capture_pcm_hook; | ||
4577 | 3407 | ||
4578 | /* hook for controlling mic-mute LED GPIO */ | 3408 | spec->gen.automute_hook = stac_update_outputs; |
4579 | static int stac92xx_capture_sw_put_led(struct snd_kcontrol *kcontrol, | 3409 | spec->gen.hp_automute_hook = stac_hp_automute; |
4580 | struct snd_ctl_elem_value *ucontrol) | 3410 | spec->gen.line_automute_hook = stac_line_automute; |
4581 | { | ||
4582 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4583 | struct sigmatel_spec *spec = codec->spec; | ||
4584 | int err; | ||
4585 | bool mute; | ||
4586 | 3411 | ||
4587 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 3412 | err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); |
4588 | if (err <= 0) | ||
4589 | return err; | ||
4590 | mute = !(ucontrol->value.integer.value[0] && | ||
4591 | ucontrol->value.integer.value[1]); | ||
4592 | if (spec->mic_mute_led_on != mute) { | ||
4593 | spec->mic_mute_led_on = mute; | ||
4594 | if (mute) | ||
4595 | spec->gpio_data |= spec->mic_mute_led_gpio; | ||
4596 | else | ||
4597 | spec->gpio_data &= ~spec->mic_mute_led_gpio; | ||
4598 | stac_gpio_set(codec, spec->gpio_mask, | ||
4599 | spec->gpio_dir, spec->gpio_data); | ||
4600 | } | ||
4601 | return err; | ||
4602 | } | ||
4603 | |||
4604 | static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol, | ||
4605 | unsigned long sw, int idx) | ||
4606 | { | ||
4607 | struct sigmatel_spec *spec = codec->spec; | ||
4608 | struct snd_kcontrol_new *knew; | ||
4609 | int err; | ||
4610 | |||
4611 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, | ||
4612 | "Capture Volume", vol); | ||
4613 | if (err < 0) | 3413 | if (err < 0) |
4614 | return err; | 3414 | return err; |
4615 | 3415 | ||
4616 | knew = add_control_temp(spec, | 3416 | /* minimum value is actually mute */ |
4617 | &stac92xx_control_templates[STAC_CTL_WIDGET_MUTE], | 3417 | spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; |
4618 | idx, "Capture Switch", sw); | ||
4619 | if (!knew) | ||
4620 | return -ENOMEM; | ||
4621 | /* add a LED hook for some HP laptops */ | ||
4622 | if (spec->mic_mute_led_gpio) | ||
4623 | knew->put = stac92xx_capture_sw_put_led; | ||
4624 | |||
4625 | return 0; | ||
4626 | } | ||
4627 | |||
4628 | /* add playback controls from the parsed DAC table */ | ||
4629 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
4630 | const struct auto_pin_cfg *cfg) | ||
4631 | { | ||
4632 | struct sigmatel_spec *spec = codec->spec; | ||
4633 | hda_nid_t nid; | ||
4634 | int err; | ||
4635 | int idx; | ||
4636 | |||
4637 | err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, | ||
4638 | spec->multiout.dac_nids, | ||
4639 | cfg->line_out_type); | ||
4640 | if (err < 0) | ||
4641 | return err; | ||
4642 | |||
4643 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | ||
4644 | err = stac92xx_add_control(spec, | ||
4645 | STAC_CTL_WIDGET_HP_SWITCH, | ||
4646 | "Headphone as Line Out Switch", | ||
4647 | cfg->hp_pins[cfg->hp_outs - 1]); | ||
4648 | if (err < 0) | ||
4649 | return err; | ||
4650 | } | ||
4651 | |||
4652 | for (idx = 0; idx < cfg->num_inputs; idx++) { | ||
4653 | if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN) | ||
4654 | break; | ||
4655 | nid = cfg->inputs[idx].pin; | ||
4656 | err = stac92xx_add_jack_mode_control(codec, nid, idx); | ||
4657 | if (err < 0) | ||
4658 | return err; | ||
4659 | } | ||
4660 | |||
4661 | return 0; | ||
4662 | } | ||
4663 | |||
4664 | /* add playback controls for Speaker and HP outputs */ | ||
4665 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | ||
4666 | struct auto_pin_cfg *cfg) | ||
4667 | { | ||
4668 | struct sigmatel_spec *spec = codec->spec; | ||
4669 | int err; | ||
4670 | |||
4671 | err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins, | ||
4672 | spec->hp_dacs, AUTO_PIN_HP_OUT); | ||
4673 | if (err < 0) | ||
4674 | return err; | ||
4675 | |||
4676 | err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, | ||
4677 | spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT); | ||
4678 | if (err < 0) | ||
4679 | return err; | ||
4680 | |||
4681 | return 0; | ||
4682 | } | ||
4683 | |||
4684 | /* labels for mono mux outputs */ | ||
4685 | static const char * const stac92xx_mono_labels[4] = { | ||
4686 | "DAC0", "DAC1", "Mixer", "DAC2" | ||
4687 | }; | ||
4688 | |||
4689 | /* create mono mux for mono out on capable codecs */ | ||
4690 | static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | ||
4691 | { | ||
4692 | struct sigmatel_spec *spec = codec->spec; | ||
4693 | struct hda_input_mux *mono_mux = &spec->private_mono_mux; | ||
4694 | int i, num_cons; | ||
4695 | hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)]; | ||
4696 | |||
4697 | num_cons = snd_hda_get_connections(codec, | ||
4698 | spec->mono_nid, | ||
4699 | con_lst, | ||
4700 | HDA_MAX_NUM_INPUTS); | ||
4701 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | ||
4702 | return -EINVAL; | ||
4703 | |||
4704 | for (i = 0; i < num_cons; i++) | ||
4705 | snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i, | ||
4706 | NULL); | ||
4707 | |||
4708 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | ||
4709 | "Mono Mux", spec->mono_nid); | ||
4710 | } | ||
4711 | |||
4712 | /* create PC beep volume controls */ | ||
4713 | static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, | ||
4714 | hda_nid_t nid) | ||
4715 | { | ||
4716 | struct sigmatel_spec *spec = codec->spec; | ||
4717 | u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); | ||
4718 | int err, type = STAC_CTL_WIDGET_MUTE_BEEP; | ||
4719 | |||
4720 | if (spec->anabeep_nid == nid) | ||
4721 | type = STAC_CTL_WIDGET_MUTE; | ||
4722 | |||
4723 | /* check for mute support for the the amp */ | ||
4724 | if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { | ||
4725 | err = stac92xx_add_control(spec, type, | ||
4726 | "Beep Playback Switch", | ||
4727 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); | ||
4728 | if (err < 0) | ||
4729 | return err; | ||
4730 | } | ||
4731 | |||
4732 | /* check to see if there is volume support for the amp */ | ||
4733 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { | ||
4734 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, | ||
4735 | "Beep Playback Volume", | ||
4736 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); | ||
4737 | if (err < 0) | ||
4738 | return err; | ||
4739 | } | ||
4740 | return 0; | ||
4741 | } | ||
4742 | |||
4743 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
4744 | #define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info | ||
4745 | |||
4746 | static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol, | ||
4747 | struct snd_ctl_elem_value *ucontrol) | ||
4748 | { | ||
4749 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4750 | ucontrol->value.integer.value[0] = codec->beep->enabled; | ||
4751 | return 0; | ||
4752 | } | ||
4753 | |||
4754 | static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol, | ||
4755 | struct snd_ctl_elem_value *ucontrol) | ||
4756 | { | ||
4757 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4758 | return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]); | ||
4759 | } | ||
4760 | |||
4761 | static const struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { | ||
4762 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4763 | .info = stac92xx_dig_beep_switch_info, | ||
4764 | .get = stac92xx_dig_beep_switch_get, | ||
4765 | .put = stac92xx_dig_beep_switch_put, | ||
4766 | }; | ||
4767 | |||
4768 | static int stac92xx_beep_switch_ctl(struct hda_codec *codec) | ||
4769 | { | ||
4770 | return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl, | ||
4771 | 0, "Beep Playback Switch", 0); | ||
4772 | } | ||
4773 | #endif | ||
4774 | |||
4775 | static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) | ||
4776 | { | ||
4777 | struct sigmatel_spec *spec = codec->spec; | ||
4778 | int i, j, err = 0; | ||
4779 | |||
4780 | for (i = 0; i < spec->num_muxes; i++) { | ||
4781 | hda_nid_t nid; | ||
4782 | unsigned int wcaps; | ||
4783 | unsigned long val; | ||
4784 | |||
4785 | nid = spec->mux_nids[i]; | ||
4786 | wcaps = get_wcaps(codec, nid); | ||
4787 | if (!(wcaps & AC_WCAP_OUT_AMP)) | ||
4788 | continue; | ||
4789 | |||
4790 | /* check whether already the same control was created as | ||
4791 | * normal Capture Volume. | ||
4792 | */ | ||
4793 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
4794 | for (j = 0; j < spec->num_caps; j++) { | ||
4795 | if (spec->capvols[j] == val) | ||
4796 | break; | ||
4797 | } | ||
4798 | if (j < spec->num_caps) | ||
4799 | continue; | ||
4800 | |||
4801 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, i, | ||
4802 | "Mux Capture Volume", val); | ||
4803 | if (err < 0) | ||
4804 | return err; | ||
4805 | } | ||
4806 | return 0; | ||
4807 | }; | ||
4808 | |||
4809 | static const char * const stac92xx_spdif_labels[3] = { | ||
4810 | "Digital Playback", "Analog Mux 1", "Analog Mux 2", | ||
4811 | }; | ||
4812 | |||
4813 | static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | ||
4814 | { | ||
4815 | struct sigmatel_spec *spec = codec->spec; | ||
4816 | struct hda_input_mux *spdif_mux = &spec->private_smux; | ||
4817 | const char * const *labels = spec->spdif_labels; | ||
4818 | int i, num_cons; | ||
4819 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | ||
4820 | |||
4821 | num_cons = snd_hda_get_connections(codec, | ||
4822 | spec->smux_nids[0], | ||
4823 | con_lst, | ||
4824 | HDA_MAX_NUM_INPUTS); | ||
4825 | if (num_cons <= 0) | ||
4826 | return -EINVAL; | ||
4827 | |||
4828 | if (!labels) | ||
4829 | labels = stac92xx_spdif_labels; | ||
4830 | |||
4831 | for (i = 0; i < num_cons; i++) | ||
4832 | snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL); | ||
4833 | |||
4834 | return 0; | ||
4835 | } | ||
4836 | |||
4837 | /* labels for dmic mux inputs */ | ||
4838 | static const char * const stac92xx_dmic_labels[5] = { | ||
4839 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | ||
4840 | "Digital Mic 3", "Digital Mic 4" | ||
4841 | }; | ||
4842 | |||
4843 | static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux, | ||
4844 | int idx) | ||
4845 | { | ||
4846 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
4847 | int nums; | ||
4848 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
4849 | if (idx >= 0 && idx < nums) | ||
4850 | return conn[idx]; | ||
4851 | return 0; | ||
4852 | } | ||
4853 | |||
4854 | /* look for NID recursively */ | ||
4855 | #define get_connection_index(codec, mux, nid) \ | ||
4856 | snd_hda_get_conn_index(codec, mux, nid, 1) | ||
4857 | |||
4858 | /* create a volume assigned to the given pin (only if supported) */ | ||
4859 | /* return 1 if the volume control is created */ | ||
4860 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | ||
4861 | const char *label, int idx, int direction) | ||
4862 | { | ||
4863 | unsigned int caps, nums; | ||
4864 | char name[32]; | ||
4865 | int err; | ||
4866 | |||
4867 | if (direction == HDA_OUTPUT) | ||
4868 | caps = AC_WCAP_OUT_AMP; | ||
4869 | else | ||
4870 | caps = AC_WCAP_IN_AMP; | ||
4871 | if (!(get_wcaps(codec, nid) & caps)) | ||
4872 | return 0; | ||
4873 | caps = query_amp_caps(codec, nid, direction); | ||
4874 | nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
4875 | if (!nums) | ||
4876 | return 0; | ||
4877 | snprintf(name, sizeof(name), "%s Capture Volume", label); | ||
4878 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, | ||
4879 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); | ||
4880 | if (err < 0) | ||
4881 | return err; | ||
4882 | return 1; | ||
4883 | } | ||
4884 | |||
4885 | /* create playback/capture controls for input pins on dmic capable codecs */ | ||
4886 | static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | ||
4887 | const struct auto_pin_cfg *cfg) | ||
4888 | { | ||
4889 | struct sigmatel_spec *spec = codec->spec; | ||
4890 | struct hda_input_mux *imux = &spec->private_imux; | ||
4891 | struct hda_input_mux *dimux = &spec->private_dimux; | ||
4892 | int err, i; | ||
4893 | unsigned int def_conf; | ||
4894 | |||
4895 | snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL); | ||
4896 | |||
4897 | for (i = 0; i < spec->num_dmics; i++) { | ||
4898 | hda_nid_t nid; | ||
4899 | int index, type_idx; | ||
4900 | char label[32]; | ||
4901 | |||
4902 | nid = spec->dmic_nids[i]; | ||
4903 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) | ||
4904 | continue; | ||
4905 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4906 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | ||
4907 | continue; | ||
4908 | |||
4909 | index = get_connection_index(codec, spec->dmux_nids[0], nid); | ||
4910 | if (index < 0) | ||
4911 | continue; | ||
4912 | |||
4913 | snd_hda_get_pin_label(codec, nid, &spec->autocfg, | ||
4914 | label, sizeof(label), NULL); | ||
4915 | snd_hda_add_imux_item(dimux, label, index, &type_idx); | ||
4916 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) | ||
4917 | snd_hda_add_imux_item(imux, label, index, &type_idx); | ||
4918 | |||
4919 | err = create_elem_capture_vol(codec, nid, label, type_idx, | ||
4920 | HDA_INPUT); | ||
4921 | if (err < 0) | ||
4922 | return err; | ||
4923 | if (!err) { | ||
4924 | err = create_elem_capture_vol(codec, nid, label, | ||
4925 | type_idx, HDA_OUTPUT); | ||
4926 | if (err < 0) | ||
4927 | return err; | ||
4928 | if (!err) { | ||
4929 | nid = get_connected_node(codec, | ||
4930 | spec->dmux_nids[0], index); | ||
4931 | if (nid) | ||
4932 | err = create_elem_capture_vol(codec, | ||
4933 | nid, label, | ||
4934 | type_idx, HDA_INPUT); | ||
4935 | if (err < 0) | ||
4936 | return err; | ||
4937 | } | ||
4938 | } | ||
4939 | } | ||
4940 | |||
4941 | return 0; | ||
4942 | } | ||
4943 | |||
4944 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, | ||
4945 | hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock) | ||
4946 | { | ||
4947 | unsigned int cfg; | ||
4948 | unsigned int type; | ||
4949 | |||
4950 | if (!nid) | ||
4951 | return 0; | ||
4952 | cfg = snd_hda_codec_get_pincfg(codec, nid); | ||
4953 | type = get_defcfg_device(cfg); | ||
4954 | switch (snd_hda_get_input_pin_attr(cfg)) { | ||
4955 | case INPUT_PIN_ATTR_INT: | ||
4956 | if (*fixed) | ||
4957 | return 1; /* already occupied */ | ||
4958 | if (type != AC_JACK_MIC_IN) | ||
4959 | return 1; /* invalid type */ | ||
4960 | *fixed = nid; | ||
4961 | break; | ||
4962 | case INPUT_PIN_ATTR_UNUSED: | ||
4963 | break; | ||
4964 | case INPUT_PIN_ATTR_DOCK: | ||
4965 | if (*dock) | ||
4966 | return 1; /* already occupied */ | ||
4967 | if (type != AC_JACK_MIC_IN && type != AC_JACK_LINE_IN) | ||
4968 | return 1; /* invalid type */ | ||
4969 | *dock = nid; | ||
4970 | break; | ||
4971 | default: | ||
4972 | if (*ext) | ||
4973 | return 1; /* already occupied */ | ||
4974 | if (type != AC_JACK_MIC_IN) | ||
4975 | return 1; /* invalid type */ | ||
4976 | *ext = nid; | ||
4977 | break; | ||
4978 | } | ||
4979 | return 0; | ||
4980 | } | ||
4981 | |||
4982 | static int set_mic_route(struct hda_codec *codec, | ||
4983 | struct sigmatel_mic_route *mic, | ||
4984 | hda_nid_t pin) | ||
4985 | { | ||
4986 | struct sigmatel_spec *spec = codec->spec; | ||
4987 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
4988 | int i; | ||
4989 | |||
4990 | mic->pin = pin; | ||
4991 | if (pin == 0) | ||
4992 | return 0; | ||
4993 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4994 | if (pin == cfg->inputs[i].pin) | ||
4995 | break; | ||
4996 | } | ||
4997 | if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) { | ||
4998 | /* analog pin */ | ||
4999 | i = get_connection_index(codec, spec->mux_nids[0], pin); | ||
5000 | if (i < 0) | ||
5001 | return -1; | ||
5002 | mic->mux_idx = i; | ||
5003 | mic->dmux_idx = -1; | ||
5004 | if (spec->dmux_nids) | ||
5005 | mic->dmux_idx = get_connection_index(codec, | ||
5006 | spec->dmux_nids[0], | ||
5007 | spec->mux_nids[0]); | ||
5008 | } else if (spec->dmux_nids) { | ||
5009 | /* digital pin */ | ||
5010 | i = get_connection_index(codec, spec->dmux_nids[0], pin); | ||
5011 | if (i < 0) | ||
5012 | return -1; | ||
5013 | mic->dmux_idx = i; | ||
5014 | mic->mux_idx = -1; | ||
5015 | if (spec->mux_nids) | ||
5016 | mic->mux_idx = get_connection_index(codec, | ||
5017 | spec->mux_nids[0], | ||
5018 | spec->dmux_nids[0]); | ||
5019 | } | ||
5020 | return 0; | ||
5021 | } | ||
5022 | |||
5023 | /* return non-zero if the device is for automatic mic switch */ | ||
5024 | static int stac_check_auto_mic(struct hda_codec *codec) | ||
5025 | { | ||
5026 | struct sigmatel_spec *spec = codec->spec; | ||
5027 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5028 | hda_nid_t fixed, ext, dock; | ||
5029 | int i; | ||
5030 | |||
5031 | fixed = ext = dock = 0; | ||
5032 | for (i = 0; i < cfg->num_inputs; i++) | ||
5033 | if (check_mic_pin(codec, cfg->inputs[i].pin, | ||
5034 | &fixed, &ext, &dock)) | ||
5035 | return 0; | ||
5036 | for (i = 0; i < spec->num_dmics; i++) | ||
5037 | if (check_mic_pin(codec, spec->dmic_nids[i], | ||
5038 | &fixed, &ext, &dock)) | ||
5039 | return 0; | ||
5040 | if (!fixed || (!ext && !dock)) | ||
5041 | return 0; /* no input to switch */ | ||
5042 | if (!is_jack_detectable(codec, ext)) | ||
5043 | return 0; /* no unsol support */ | ||
5044 | if (set_mic_route(codec, &spec->ext_mic, ext) || | ||
5045 | set_mic_route(codec, &spec->int_mic, fixed) || | ||
5046 | set_mic_route(codec, &spec->dock_mic, dock)) | ||
5047 | return 0; /* something is wrong */ | ||
5048 | return 1; | ||
5049 | } | ||
5050 | |||
5051 | /* create playback/capture controls for input pins */ | ||
5052 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
5053 | { | ||
5054 | struct sigmatel_spec *spec = codec->spec; | ||
5055 | struct hda_input_mux *imux = &spec->private_imux; | ||
5056 | int i, j; | ||
5057 | const char *label; | ||
5058 | |||
5059 | for (i = 0; i < cfg->num_inputs; i++) { | ||
5060 | hda_nid_t nid = cfg->inputs[i].pin; | ||
5061 | int index, err, type_idx; | ||
5062 | |||
5063 | index = -1; | ||
5064 | for (j = 0; j < spec->num_muxes; j++) { | ||
5065 | index = get_connection_index(codec, spec->mux_nids[j], | ||
5066 | nid); | ||
5067 | if (index >= 0) | ||
5068 | break; | ||
5069 | } | ||
5070 | if (index < 0) | ||
5071 | continue; | ||
5072 | |||
5073 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
5074 | snd_hda_add_imux_item(imux, label, index, &type_idx); | ||
5075 | |||
5076 | err = create_elem_capture_vol(codec, nid, | ||
5077 | label, type_idx, | ||
5078 | HDA_INPUT); | ||
5079 | if (err < 0) | ||
5080 | return err; | ||
5081 | } | ||
5082 | spec->num_analog_muxes = imux->num_items; | ||
5083 | |||
5084 | if (imux->num_items) { | ||
5085 | /* | ||
5086 | * Set the current input for the muxes. | ||
5087 | * The STAC9221 has two input muxes with identical source | ||
5088 | * NID lists. Hopefully this won't get confused. | ||
5089 | */ | ||
5090 | for (i = 0; i < spec->num_muxes; i++) { | ||
5091 | snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0, | ||
5092 | AC_VERB_SET_CONNECT_SEL, | ||
5093 | imux->items[0].index); | ||
5094 | } | ||
5095 | } | ||
5096 | |||
5097 | return 0; | ||
5098 | } | ||
5099 | |||
5100 | static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | ||
5101 | { | ||
5102 | struct sigmatel_spec *spec = codec->spec; | ||
5103 | int i; | ||
5104 | |||
5105 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
5106 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
5107 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
5108 | } | ||
5109 | } | ||
5110 | |||
5111 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | ||
5112 | { | ||
5113 | struct sigmatel_spec *spec = codec->spec; | ||
5114 | int i; | ||
5115 | |||
5116 | for (i = 0; i < spec->autocfg.hp_outs; i++) { | ||
5117 | hda_nid_t pin; | ||
5118 | pin = spec->autocfg.hp_pins[i]; | ||
5119 | if (pin) /* connect to front */ | ||
5120 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
5121 | } | ||
5122 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { | ||
5123 | hda_nid_t pin; | ||
5124 | pin = spec->autocfg.speaker_pins[i]; | ||
5125 | if (pin) /* connect to front */ | ||
5126 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); | ||
5127 | } | ||
5128 | } | ||
5129 | |||
5130 | static int is_dual_headphones(struct hda_codec *codec) | ||
5131 | { | ||
5132 | struct sigmatel_spec *spec = codec->spec; | ||
5133 | int i, valid_hps; | ||
5134 | |||
5135 | if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT || | ||
5136 | spec->autocfg.hp_outs <= 1) | ||
5137 | return 0; | ||
5138 | valid_hps = 0; | ||
5139 | for (i = 0; i < spec->autocfg.hp_outs; i++) { | ||
5140 | hda_nid_t nid = spec->autocfg.hp_pins[i]; | ||
5141 | unsigned int cfg = snd_hda_codec_get_pincfg(codec, nid); | ||
5142 | if (get_defcfg_location(cfg) & AC_JACK_LOC_SEPARATE) | ||
5143 | continue; | ||
5144 | valid_hps++; | ||
5145 | } | ||
5146 | return (valid_hps > 1); | ||
5147 | } | ||
5148 | |||
5149 | |||
5150 | static int stac92xx_parse_auto_config(struct hda_codec *codec) | ||
5151 | { | ||
5152 | struct sigmatel_spec *spec = codec->spec; | ||
5153 | hda_nid_t dig_out = 0, dig_in = 0; | ||
5154 | int hp_swap = 0; | ||
5155 | int i, err; | ||
5156 | |||
5157 | if ((err = snd_hda_parse_pin_def_config(codec, | ||
5158 | &spec->autocfg, | ||
5159 | spec->dmic_nids)) < 0) | ||
5160 | return err; | ||
5161 | if (! spec->autocfg.line_outs) | ||
5162 | return -EINVAL; /* can't find valid pin config */ | ||
5163 | |||
5164 | /* If we have no real line-out pin and multiple hp-outs, HPs should | ||
5165 | * be set up as multi-channel outputs. | ||
5166 | */ | ||
5167 | if (is_dual_headphones(codec)) { | ||
5168 | /* Copy hp_outs to line_outs, backup line_outs in | ||
5169 | * speaker_outs so that the following routines can handle | ||
5170 | * HP pins as primary outputs. | ||
5171 | */ | ||
5172 | snd_printdd("stac92xx: Enabling multi-HPs workaround\n"); | ||
5173 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, | ||
5174 | sizeof(spec->autocfg.line_out_pins)); | ||
5175 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; | ||
5176 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, | ||
5177 | sizeof(spec->autocfg.hp_pins)); | ||
5178 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | ||
5179 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | ||
5180 | spec->autocfg.hp_outs = 0; | ||
5181 | hp_swap = 1; | ||
5182 | } | ||
5183 | if (spec->autocfg.mono_out_pin) { | ||
5184 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | ||
5185 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); | ||
5186 | u32 caps = query_amp_caps(codec, | ||
5187 | spec->autocfg.mono_out_pin, dir); | ||
5188 | hda_nid_t conn_list[1]; | ||
5189 | |||
5190 | /* get the mixer node and then the mono mux if it exists */ | ||
5191 | if (snd_hda_get_connections(codec, | ||
5192 | spec->autocfg.mono_out_pin, conn_list, 1) && | ||
5193 | snd_hda_get_connections(codec, conn_list[0], | ||
5194 | conn_list, 1) > 0) { | ||
5195 | |||
5196 | int wcaps = get_wcaps(codec, conn_list[0]); | ||
5197 | int wid_type = get_wcaps_type(wcaps); | ||
5198 | /* LR swap check, some stac925x have a mux that | ||
5199 | * changes the DACs output path instead of the | ||
5200 | * mono-mux path. | ||
5201 | */ | ||
5202 | if (wid_type == AC_WID_AUD_SEL && | ||
5203 | !(wcaps & AC_WCAP_LR_SWAP)) | ||
5204 | spec->mono_nid = conn_list[0]; | ||
5205 | } | ||
5206 | if (dir) { | ||
5207 | hda_nid_t nid = spec->autocfg.mono_out_pin; | ||
5208 | |||
5209 | /* most mono outs have a least a mute/unmute switch */ | ||
5210 | dir = (dir & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; | ||
5211 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, | ||
5212 | "Mono Playback Switch", | ||
5213 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); | ||
5214 | if (err < 0) | ||
5215 | return err; | ||
5216 | /* check for volume support for the amp */ | ||
5217 | if ((caps & AC_AMPCAP_NUM_STEPS) | ||
5218 | >> AC_AMPCAP_NUM_STEPS_SHIFT) { | ||
5219 | err = stac92xx_add_control(spec, | ||
5220 | STAC_CTL_WIDGET_VOL, | ||
5221 | "Mono Playback Volume", | ||
5222 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); | ||
5223 | if (err < 0) | ||
5224 | return err; | ||
5225 | } | ||
5226 | } | ||
5227 | |||
5228 | stac92xx_auto_set_pinctl(codec, spec->autocfg.mono_out_pin, | ||
5229 | AC_PINCTL_OUT_EN); | ||
5230 | } | ||
5231 | |||
5232 | if (!spec->multiout.num_dacs) { | ||
5233 | err = stac92xx_auto_fill_dac_nids(codec); | ||
5234 | if (err < 0) | ||
5235 | return err; | ||
5236 | err = stac92xx_auto_create_multi_out_ctls(codec, | ||
5237 | &spec->autocfg); | ||
5238 | if (err < 0) | ||
5239 | return err; | ||
5240 | } | ||
5241 | 3418 | ||
5242 | /* setup analog beep controls */ | 3419 | /* setup analog beep controls */ |
5243 | if (spec->anabeep_nid > 0) { | 3420 | if (spec->anabeep_nid > 0) { |
5244 | err = stac92xx_auto_create_beep_ctls(codec, | 3421 | err = stac_auto_create_beep_ctls(codec, |
5245 | spec->anabeep_nid); | 3422 | spec->anabeep_nid); |
5246 | if (err < 0) | 3423 | if (err < 0) |
5247 | return err; | 3424 | return err; |
5248 | } | 3425 | } |
@@ -5253,7 +3430,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec) | |||
5253 | hda_nid_t nid = spec->digbeep_nid; | 3430 | hda_nid_t nid = spec->digbeep_nid; |
5254 | unsigned int caps; | 3431 | unsigned int caps; |
5255 | 3432 | ||
5256 | err = stac92xx_auto_create_beep_ctls(codec, nid); | 3433 | err = stac_auto_create_beep_ctls(codec, nid); |
5257 | if (err < 0) | 3434 | if (err < 0) |
5258 | return err; | 3435 | return err; |
5259 | err = snd_hda_attach_beep_device(codec, nid); | 3436 | err = snd_hda_attach_beep_device(codec, nid); |
@@ -5265,7 +3442,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec) | |||
5265 | /* if no beep switch is available, make its own one */ | 3442 | /* if no beep switch is available, make its own one */ |
5266 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | 3443 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); |
5267 | if (!(caps & AC_AMPCAP_MUTE)) { | 3444 | if (!(caps & AC_AMPCAP_MUTE)) { |
5268 | err = stac92xx_beep_switch_ctl(codec); | 3445 | err = stac_beep_switch_ctl(codec); |
5269 | if (err < 0) | 3446 | if (err < 0) |
5270 | return err; | 3447 | return err; |
5271 | } | 3448 | } |
@@ -5273,380 +3450,27 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec) | |||
5273 | } | 3450 | } |
5274 | #endif | 3451 | #endif |
5275 | 3452 | ||
5276 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 3453 | if (spec->gpio_led) |
5277 | if (err < 0) | 3454 | spec->gen.vmaster_mute.hook = stac_vmaster_hook; |
5278 | return err; | ||
5279 | |||
5280 | /* All output parsing done, now restore the swapped hp pins */ | ||
5281 | if (hp_swap) { | ||
5282 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
5283 | sizeof(spec->autocfg.hp_pins)); | ||
5284 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
5285 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | ||
5286 | spec->autocfg.line_outs = 0; | ||
5287 | } | ||
5288 | |||
5289 | if (stac_check_auto_mic(codec)) { | ||
5290 | spec->auto_mic = 1; | ||
5291 | /* only one capture for auto-mic */ | ||
5292 | spec->num_adcs = 1; | ||
5293 | spec->num_caps = 1; | ||
5294 | spec->num_muxes = 1; | ||
5295 | } | ||
5296 | |||
5297 | for (i = 0; i < spec->num_caps; i++) { | ||
5298 | err = stac92xx_add_capvol_ctls(codec, spec->capvols[i], | ||
5299 | spec->capsws[i], i); | ||
5300 | if (err < 0) | ||
5301 | return err; | ||
5302 | } | ||
5303 | |||
5304 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
5305 | if (err < 0) | ||
5306 | return err; | ||
5307 | |||
5308 | if (spec->mono_nid > 0) { | ||
5309 | err = stac92xx_auto_create_mono_output_ctls(codec); | ||
5310 | if (err < 0) | ||
5311 | return err; | ||
5312 | } | ||
5313 | if (spec->num_dmics > 0 && !spec->dinput_mux) | ||
5314 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, | ||
5315 | &spec->autocfg)) < 0) | ||
5316 | return err; | ||
5317 | if (spec->num_muxes > 0) { | ||
5318 | err = stac92xx_auto_create_mux_input_ctls(codec); | ||
5319 | if (err < 0) | ||
5320 | return err; | ||
5321 | } | ||
5322 | if (spec->num_smuxes > 0) { | ||
5323 | err = stac92xx_auto_create_spdif_mux_ctls(codec); | ||
5324 | if (err < 0) | ||
5325 | return err; | ||
5326 | } | ||
5327 | |||
5328 | err = stac92xx_add_input_source(spec); | ||
5329 | if (err < 0) | ||
5330 | return err; | ||
5331 | |||
5332 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
5333 | if (spec->multiout.max_channels > 2) | ||
5334 | spec->surr_switch = 1; | ||
5335 | |||
5336 | /* find digital out and in converters */ | ||
5337 | for (i = codec->start_nid; i < codec->start_nid + codec->num_nodes; i++) { | ||
5338 | unsigned int wid_caps = get_wcaps(codec, i); | ||
5339 | if (wid_caps & AC_WCAP_DIGITAL) { | ||
5340 | switch (get_wcaps_type(wid_caps)) { | ||
5341 | case AC_WID_AUD_OUT: | ||
5342 | if (!dig_out) | ||
5343 | dig_out = i; | ||
5344 | break; | ||
5345 | case AC_WID_AUD_IN: | ||
5346 | if (!dig_in) | ||
5347 | dig_in = i; | ||
5348 | break; | ||
5349 | } | ||
5350 | } | ||
5351 | } | ||
5352 | if (spec->autocfg.dig_outs) | ||
5353 | spec->multiout.dig_out_nid = dig_out; | ||
5354 | if (dig_in && spec->autocfg.dig_in_pin) | ||
5355 | spec->dig_in_nid = dig_in; | ||
5356 | |||
5357 | if (spec->kctls.list) | ||
5358 | spec->mixers[spec->num_mixers++] = spec->kctls.list; | ||
5359 | |||
5360 | spec->input_mux = &spec->private_imux; | ||
5361 | if (!spec->dinput_mux) | ||
5362 | spec->dinput_mux = &spec->private_dimux; | ||
5363 | spec->sinput_mux = &spec->private_smux; | ||
5364 | spec->mono_mux = &spec->private_mono_mux; | ||
5365 | return 0; | ||
5366 | } | ||
5367 | |||
5368 | /* add playback controls for HP output */ | ||
5369 | static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | ||
5370 | struct auto_pin_cfg *cfg) | ||
5371 | { | ||
5372 | struct sigmatel_spec *spec = codec->spec; | ||
5373 | hda_nid_t pin = cfg->hp_pins[0]; | ||
5374 | |||
5375 | if (! pin) | ||
5376 | return 0; | ||
5377 | |||
5378 | if (is_jack_detectable(codec, pin)) | ||
5379 | spec->hp_detect = 1; | ||
5380 | |||
5381 | return 0; | ||
5382 | } | ||
5383 | |||
5384 | /* add playback controls for LFE output */ | ||
5385 | static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | ||
5386 | struct auto_pin_cfg *cfg) | ||
5387 | { | ||
5388 | struct sigmatel_spec *spec = codec->spec; | ||
5389 | int err; | ||
5390 | hda_nid_t lfe_pin = 0x0; | ||
5391 | int i; | ||
5392 | |||
5393 | /* | ||
5394 | * search speaker outs and line outs for a mono speaker pin | ||
5395 | * with an amp. If one is found, add LFE controls | ||
5396 | * for it. | ||
5397 | */ | ||
5398 | for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { | ||
5399 | hda_nid_t pin = spec->autocfg.speaker_pins[i]; | ||
5400 | unsigned int wcaps = get_wcaps(codec, pin); | ||
5401 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
5402 | if (wcaps == AC_WCAP_OUT_AMP) | ||
5403 | /* found a mono speaker with an amp, must be lfe */ | ||
5404 | lfe_pin = pin; | ||
5405 | } | ||
5406 | |||
5407 | /* if speaker_outs is 0, then speakers may be in line_outs */ | ||
5408 | if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { | ||
5409 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | ||
5410 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | ||
5411 | unsigned int defcfg; | ||
5412 | defcfg = snd_hda_codec_get_pincfg(codec, pin); | ||
5413 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { | ||
5414 | unsigned int wcaps = get_wcaps(codec, pin); | ||
5415 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
5416 | if (wcaps == AC_WCAP_OUT_AMP) | ||
5417 | /* found a mono speaker with an amp, | ||
5418 | must be lfe */ | ||
5419 | lfe_pin = pin; | ||
5420 | } | ||
5421 | } | ||
5422 | } | ||
5423 | |||
5424 | if (lfe_pin) { | ||
5425 | err = create_controls(codec, "LFE", lfe_pin, 1); | ||
5426 | if (err < 0) | ||
5427 | return err; | ||
5428 | } | ||
5429 | |||
5430 | return 0; | ||
5431 | } | ||
5432 | |||
5433 | static int stac9200_parse_auto_config(struct hda_codec *codec) | ||
5434 | { | ||
5435 | struct sigmatel_spec *spec = codec->spec; | ||
5436 | int err; | ||
5437 | |||
5438 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | ||
5439 | return err; | ||
5440 | |||
5441 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | ||
5442 | return err; | ||
5443 | |||
5444 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) | ||
5445 | return err; | ||
5446 | |||
5447 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) | ||
5448 | return err; | ||
5449 | 3455 | ||
5450 | if (spec->num_muxes > 0) { | 3456 | if (spec->aloopback_ctl && |
5451 | err = stac92xx_auto_create_mux_input_ctls(codec); | 3457 | snd_hda_get_bool_hint(codec, "loopback") == 1) { |
5452 | if (err < 0) | 3458 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl)) |
5453 | return err; | 3459 | return -ENOMEM; |
5454 | } | 3460 | } |
5455 | 3461 | ||
5456 | err = stac92xx_add_input_source(spec); | 3462 | stac_init_power_map(codec); |
5457 | if (err < 0) | ||
5458 | return err; | ||
5459 | |||
5460 | if (spec->autocfg.dig_outs) | ||
5461 | spec->multiout.dig_out_nid = 0x05; | ||
5462 | if (spec->autocfg.dig_in_pin) | ||
5463 | spec->dig_in_nid = 0x04; | ||
5464 | |||
5465 | if (spec->kctls.list) | ||
5466 | spec->mixers[spec->num_mixers++] = spec->kctls.list; | ||
5467 | |||
5468 | spec->input_mux = &spec->private_imux; | ||
5469 | spec->dinput_mux = &spec->private_dimux; | ||
5470 | |||
5471 | return 0; | ||
5472 | } | ||
5473 | |||
5474 | /* | ||
5475 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a | ||
5476 | * funky external mute control using GPIO pins. | ||
5477 | */ | ||
5478 | |||
5479 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | ||
5480 | unsigned int dir_mask, unsigned int data) | ||
5481 | { | ||
5482 | unsigned int gpiostate, gpiomask, gpiodir; | ||
5483 | |||
5484 | snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); | ||
5485 | |||
5486 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | ||
5487 | AC_VERB_GET_GPIO_DATA, 0); | ||
5488 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | ||
5489 | |||
5490 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | ||
5491 | AC_VERB_GET_GPIO_MASK, 0); | ||
5492 | gpiomask |= mask; | ||
5493 | |||
5494 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | ||
5495 | AC_VERB_GET_GPIO_DIRECTION, 0); | ||
5496 | gpiodir |= dir_mask; | ||
5497 | |||
5498 | /* Configure GPIOx as CMOS */ | ||
5499 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | ||
5500 | |||
5501 | snd_hda_codec_write(codec, codec->afg, 0, | ||
5502 | AC_VERB_SET_GPIO_MASK, gpiomask); | ||
5503 | snd_hda_codec_read(codec, codec->afg, 0, | ||
5504 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ | ||
5505 | |||
5506 | msleep(1); | ||
5507 | |||
5508 | snd_hda_codec_read(codec, codec->afg, 0, | ||
5509 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | ||
5510 | } | ||
5511 | |||
5512 | static int stac_add_event(struct hda_codec *codec, hda_nid_t nid, | ||
5513 | unsigned char type, int data) | ||
5514 | { | ||
5515 | struct hda_jack_tbl *event; | ||
5516 | |||
5517 | event = snd_hda_jack_tbl_new(codec, nid); | ||
5518 | if (!event) | ||
5519 | return -ENOMEM; | ||
5520 | event->action = type; | ||
5521 | event->private_data = data; | ||
5522 | 3463 | ||
5523 | return 0; | 3464 | return 0; |
5524 | } | 3465 | } |
5525 | 3466 | ||
5526 | static void handle_unsol_event(struct hda_codec *codec, | ||
5527 | struct hda_jack_tbl *event); | ||
5528 | |||
5529 | /* check if given nid is a valid pin and no other events are assigned | ||
5530 | * to it. If OK, assign the event, set the unsol flag, and returns 1. | ||
5531 | * Otherwise, returns zero. | ||
5532 | */ | ||
5533 | static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | ||
5534 | unsigned int type) | ||
5535 | { | ||
5536 | struct hda_jack_tbl *event; | ||
5537 | |||
5538 | if (!is_jack_detectable(codec, nid)) | ||
5539 | return 0; | ||
5540 | event = snd_hda_jack_tbl_new(codec, nid); | ||
5541 | if (!event) | ||
5542 | return -ENOMEM; | ||
5543 | if (event->action && event->action != type) | ||
5544 | return 0; | ||
5545 | event->action = type; | ||
5546 | event->callback = handle_unsol_event; | ||
5547 | snd_hda_jack_detect_enable(codec, nid, 0); | ||
5548 | return 1; | ||
5549 | } | ||
5550 | |||
5551 | static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | ||
5552 | { | ||
5553 | int i; | ||
5554 | for (i = 0; i < cfg->hp_outs; i++) | ||
5555 | if (cfg->hp_pins[i] == nid) | ||
5556 | return 1; /* nid is a HP-Out */ | ||
5557 | for (i = 0; i < cfg->line_outs; i++) | ||
5558 | if (cfg->line_out_pins[i] == nid) | ||
5559 | return 1; /* nid is a line-Out */ | ||
5560 | return 0; /* nid is not a HP-Out */ | ||
5561 | }; | ||
5562 | |||
5563 | static void stac92xx_power_down(struct hda_codec *codec) | ||
5564 | { | ||
5565 | struct sigmatel_spec *spec = codec->spec; | ||
5566 | |||
5567 | /* power down inactive DACs */ | ||
5568 | const hda_nid_t *dac; | ||
5569 | for (dac = spec->dac_list; *dac; dac++) | ||
5570 | if (!check_all_dac_nids(spec, *dac)) | ||
5571 | snd_hda_codec_write(codec, *dac, 0, | ||
5572 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5573 | } | ||
5574 | |||
5575 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | ||
5576 | int enable); | ||
5577 | |||
5578 | static inline bool get_int_hint(struct hda_codec *codec, const char *key, | ||
5579 | int *valp) | ||
5580 | { | ||
5581 | return !snd_hda_get_int_hint(codec, key, valp); | ||
5582 | } | ||
5583 | |||
5584 | /* override some hints from the hwdep entry */ | ||
5585 | static void stac_store_hints(struct hda_codec *codec) | ||
5586 | { | ||
5587 | struct sigmatel_spec *spec = codec->spec; | ||
5588 | int val; | ||
5589 | 3467 | ||
5590 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | 3468 | static int stac_init(struct hda_codec *codec) |
5591 | if (val >= 0) | ||
5592 | spec->hp_detect = val; | ||
5593 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { | ||
5594 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | ||
5595 | spec->gpio_mask; | ||
5596 | } | ||
5597 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) | ||
5598 | spec->gpio_mask &= spec->gpio_mask; | ||
5599 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) | ||
5600 | spec->gpio_dir &= spec->gpio_mask; | ||
5601 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) | ||
5602 | spec->eapd_mask &= spec->gpio_mask; | ||
5603 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) | ||
5604 | spec->gpio_mute &= spec->gpio_mask; | ||
5605 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | ||
5606 | if (val >= 0) | ||
5607 | spec->eapd_switch = val; | ||
5608 | } | ||
5609 | |||
5610 | static void stac_issue_unsol_events(struct hda_codec *codec, int num_pins, | ||
5611 | const hda_nid_t *pins) | ||
5612 | { | ||
5613 | while (num_pins--) | ||
5614 | stac_issue_unsol_event(codec, *pins++); | ||
5615 | } | ||
5616 | |||
5617 | /* fake event to set up pins */ | ||
5618 | static void stac_fake_hp_events(struct hda_codec *codec) | ||
5619 | { | ||
5620 | struct sigmatel_spec *spec = codec->spec; | ||
5621 | |||
5622 | if (spec->autocfg.hp_outs) | ||
5623 | stac_issue_unsol_events(codec, spec->autocfg.hp_outs, | ||
5624 | spec->autocfg.hp_pins); | ||
5625 | if (spec->autocfg.line_outs && | ||
5626 | spec->autocfg.line_out_pins[0] != spec->autocfg.hp_pins[0]) | ||
5627 | stac_issue_unsol_events(codec, spec->autocfg.line_outs, | ||
5628 | spec->autocfg.line_out_pins); | ||
5629 | } | ||
5630 | |||
5631 | static int stac92xx_init(struct hda_codec *codec) | ||
5632 | { | 3469 | { |
5633 | struct sigmatel_spec *spec = codec->spec; | 3470 | struct sigmatel_spec *spec = codec->spec; |
5634 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5635 | unsigned int gpio; | 3471 | unsigned int gpio; |
5636 | int i; | 3472 | int i; |
5637 | 3473 | ||
5638 | if (spec->init) | ||
5639 | snd_hda_sequence_write(codec, spec->init); | ||
5640 | |||
5641 | snd_hda_apply_verbs(codec); | ||
5642 | |||
5643 | /* power down adcs initially */ | ||
5644 | if (spec->powerdown_adcs) | ||
5645 | for (i = 0; i < spec->num_adcs; i++) | ||
5646 | snd_hda_codec_write(codec, | ||
5647 | spec->adc_nids[i], 0, | ||
5648 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5649 | |||
5650 | /* override some hints */ | 3474 | /* override some hints */ |
5651 | stac_store_hints(codec); | 3475 | stac_store_hints(codec); |
5652 | 3476 | ||
@@ -5659,180 +3483,41 @@ static int stac92xx_init(struct hda_codec *codec) | |||
5659 | gpio |= spec->eapd_mask; | 3483 | gpio |= spec->eapd_mask; |
5660 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio); | 3484 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio); |
5661 | 3485 | ||
5662 | /* set up pins */ | 3486 | snd_hda_gen_init(codec); |
5663 | if (spec->hp_detect) { | ||
5664 | /* Enable unsolicited responses on the HP widget */ | ||
5665 | for (i = 0; i < cfg->hp_outs; i++) { | ||
5666 | hda_nid_t nid = cfg->hp_pins[i]; | ||
5667 | enable_pin_detect(codec, nid, STAC_HP_EVENT); | ||
5668 | } | ||
5669 | if (cfg->line_out_type == AUTO_PIN_LINE_OUT && | ||
5670 | cfg->speaker_outs > 0) { | ||
5671 | /* enable pin-detect for line-outs as well */ | ||
5672 | for (i = 0; i < cfg->line_outs; i++) { | ||
5673 | hda_nid_t nid = cfg->line_out_pins[i]; | ||
5674 | enable_pin_detect(codec, nid, STAC_LO_EVENT); | ||
5675 | } | ||
5676 | } | ||
5677 | |||
5678 | /* force to enable the first line-out; the others are set up | ||
5679 | * in unsol_event | ||
5680 | */ | ||
5681 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | ||
5682 | AC_PINCTL_OUT_EN); | ||
5683 | /* fake event to set up pins */ | ||
5684 | stac_fake_hp_events(codec); | ||
5685 | } else { | ||
5686 | stac92xx_auto_init_multi_out(codec); | ||
5687 | stac92xx_auto_init_hp_out(codec); | ||
5688 | for (i = 0; i < cfg->hp_outs; i++) | ||
5689 | stac_toggle_power_map(codec, cfg->hp_pins[i], 1); | ||
5690 | } | ||
5691 | if (spec->auto_mic) { | ||
5692 | /* initialize connection to analog input */ | ||
5693 | if (spec->dmux_nids) | ||
5694 | snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, | ||
5695 | AC_VERB_SET_CONNECT_SEL, 0); | ||
5696 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) | ||
5697 | stac_issue_unsol_event(codec, spec->ext_mic.pin); | ||
5698 | if (enable_pin_detect(codec, spec->dock_mic.pin, | ||
5699 | STAC_MIC_EVENT)) | ||
5700 | stac_issue_unsol_event(codec, spec->dock_mic.pin); | ||
5701 | } | ||
5702 | for (i = 0; i < cfg->num_inputs; i++) { | ||
5703 | hda_nid_t nid = cfg->inputs[i].pin; | ||
5704 | int type = cfg->inputs[i].type; | ||
5705 | unsigned int pinctl, conf; | ||
5706 | if (type == AUTO_PIN_MIC) { | ||
5707 | /* for mic pins, force to initialize */ | ||
5708 | pinctl = snd_hda_get_default_vref(codec, nid); | ||
5709 | pinctl |= AC_PINCTL_IN_EN; | ||
5710 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
5711 | } else { | ||
5712 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
5713 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5714 | /* if PINCTL already set then skip */ | ||
5715 | /* Also, if both INPUT and OUTPUT are set, | ||
5716 | * it must be a BIOS bug; need to override, too | ||
5717 | */ | ||
5718 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
5719 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
5720 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
5721 | pinctl |= AC_PINCTL_IN_EN; | ||
5722 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
5723 | } | ||
5724 | } | ||
5725 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
5726 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
5727 | if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) | ||
5728 | stac_issue_unsol_event(codec, nid); | ||
5729 | } | ||
5730 | } | ||
5731 | for (i = 0; i < spec->num_dmics; i++) | ||
5732 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | ||
5733 | AC_PINCTL_IN_EN); | ||
5734 | if (cfg->dig_out_pins[0]) | ||
5735 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0], | ||
5736 | AC_PINCTL_OUT_EN); | ||
5737 | if (cfg->dig_in_pin) | ||
5738 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | ||
5739 | AC_PINCTL_IN_EN); | ||
5740 | for (i = 0; i < spec->num_pwrs; i++) { | ||
5741 | hda_nid_t nid = spec->pwr_nids[i]; | ||
5742 | unsigned int pinctl, def_conf; | ||
5743 | |||
5744 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
5745 | def_conf = get_defcfg_connect(def_conf); | ||
5746 | if (def_conf == AC_JACK_PORT_NONE) { | ||
5747 | /* power off unused ports */ | ||
5748 | stac_toggle_power_map(codec, nid, 0); | ||
5749 | continue; | ||
5750 | } | ||
5751 | if (def_conf == AC_JACK_PORT_FIXED) { | ||
5752 | /* no need for jack detection for fixed pins */ | ||
5753 | stac_toggle_power_map(codec, nid, 1); | ||
5754 | continue; | ||
5755 | } | ||
5756 | /* power on when no jack detection is available */ | ||
5757 | /* or when the VREF is used for controlling LED */ | ||
5758 | if (!spec->hp_detect || | ||
5759 | spec->vref_mute_led_nid == nid || | ||
5760 | !is_jack_detectable(codec, nid)) { | ||
5761 | stac_toggle_power_map(codec, nid, 1); | ||
5762 | continue; | ||
5763 | } | ||
5764 | |||
5765 | if (is_nid_out_jack_pin(cfg, nid)) | ||
5766 | continue; /* already has an unsol event */ | ||
5767 | |||
5768 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
5769 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5770 | /* outputs are only ports capable of power management | ||
5771 | * any attempts on powering down a input port cause the | ||
5772 | * referenced VREF to act quirky. | ||
5773 | */ | ||
5774 | if (pinctl & AC_PINCTL_IN_EN) { | ||
5775 | stac_toggle_power_map(codec, nid, 1); | ||
5776 | continue; | ||
5777 | } | ||
5778 | if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) { | ||
5779 | stac_issue_unsol_event(codec, nid); | ||
5780 | continue; | ||
5781 | } | ||
5782 | /* none of the above, turn the port OFF */ | ||
5783 | stac_toggle_power_map(codec, nid, 0); | ||
5784 | } | ||
5785 | |||
5786 | /* sync mute LED */ | ||
5787 | if (spec->gpio_led) { | ||
5788 | if (spec->vmaster_mute.hook) | ||
5789 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | ||
5790 | else /* the very first init call doesn't have vmaster yet */ | ||
5791 | stac92xx_update_led_status(codec, false); | ||
5792 | } | ||
5793 | 3487 | ||
5794 | /* sync the power-map */ | 3488 | /* sync the power-map */ |
5795 | if (spec->num_pwrs) | 3489 | if (spec->num_pwrs) |
5796 | snd_hda_codec_write(codec, codec->afg, 0, | 3490 | snd_hda_codec_write(codec, codec->afg, 0, |
5797 | AC_VERB_IDT_SET_POWER_MAP, | 3491 | AC_VERB_IDT_SET_POWER_MAP, |
5798 | spec->power_map_bits); | 3492 | spec->power_map_bits); |
5799 | if (spec->dac_list) | ||
5800 | stac92xx_power_down(codec); | ||
5801 | return 0; | ||
5802 | } | ||
5803 | |||
5804 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
5805 | { | ||
5806 | struct sigmatel_spec *spec = codec->spec; | ||
5807 | 3493 | ||
5808 | if (spec->kctls.list) { | 3494 | /* power down inactive ADCs */ |
5809 | struct snd_kcontrol_new *kctl = spec->kctls.list; | 3495 | if (spec->powerdown_adcs) { |
5810 | int i; | 3496 | for (i = 0; i < spec->gen.num_all_adcs; i++) { |
5811 | for (i = 0; i < spec->kctls.used; i++) | 3497 | if (spec->active_adcs & (1 << i)) |
5812 | kfree(kctl[i].name); | 3498 | continue; |
3499 | snd_hda_codec_write(codec, spec->gen.all_adcs[i], 0, | ||
3500 | AC_VERB_SET_POWER_STATE, | ||
3501 | AC_PWRST_D3); | ||
3502 | } | ||
5813 | } | 3503 | } |
5814 | snd_array_free(&spec->kctls); | ||
5815 | } | ||
5816 | |||
5817 | static void stac92xx_shutup_pins(struct hda_codec *codec) | ||
5818 | { | ||
5819 | unsigned int i, def_conf; | ||
5820 | 3504 | ||
5821 | if (codec->bus->shutdown) | 3505 | /* power down unused DACs */ |
5822 | return; | 3506 | for (i = 0; i < spec->gen.num_all_dacs; i++) { |
5823 | for (i = 0; i < codec->init_pins.used; i++) { | 3507 | if (!snd_hda_get_nid_path(codec, spec->gen.all_dacs[i], 0)) |
5824 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | 3508 | snd_hda_codec_write(codec, spec->gen.all_dacs[i], 0, |
5825 | def_conf = snd_hda_codec_get_pincfg(codec, pin->nid); | 3509 | AC_VERB_SET_POWER_STATE, |
5826 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) | 3510 | AC_PWRST_D3); |
5827 | snd_hda_set_pin_ctl(codec, pin->nid, 0); | ||
5828 | } | 3511 | } |
3512 | |||
3513 | return 0; | ||
5829 | } | 3514 | } |
5830 | 3515 | ||
5831 | static void stac92xx_shutup(struct hda_codec *codec) | 3516 | static void stac_shutup(struct hda_codec *codec) |
5832 | { | 3517 | { |
5833 | struct sigmatel_spec *spec = codec->spec; | 3518 | struct sigmatel_spec *spec = codec->spec; |
5834 | 3519 | ||
5835 | stac92xx_shutup_pins(codec); | 3520 | snd_hda_shutup_pins(codec); |
5836 | 3521 | ||
5837 | if (spec->eapd_mask) | 3522 | if (spec->eapd_mask) |
5838 | stac_gpio_set(codec, spec->gpio_mask, | 3523 | stac_gpio_set(codec, spec->gpio_mask, |
@@ -5840,459 +3525,18 @@ static void stac92xx_shutup(struct hda_codec *codec) | |||
5840 | ~spec->eapd_mask); | 3525 | ~spec->eapd_mask); |
5841 | } | 3526 | } |
5842 | 3527 | ||
5843 | static void stac92xx_free(struct hda_codec *codec) | 3528 | static void stac_free(struct hda_codec *codec) |
5844 | { | 3529 | { |
5845 | struct sigmatel_spec *spec = codec->spec; | 3530 | struct sigmatel_spec *spec = codec->spec; |
5846 | 3531 | ||
5847 | if (! spec) | 3532 | if (!spec) |
5848 | return; | 3533 | return; |
5849 | 3534 | ||
3535 | snd_hda_gen_spec_free(&spec->gen); | ||
5850 | kfree(spec); | 3536 | kfree(spec); |
5851 | snd_hda_detach_beep_device(codec); | 3537 | snd_hda_detach_beep_device(codec); |
5852 | } | 3538 | } |
5853 | 3539 | ||
5854 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
5855 | unsigned int flag) | ||
5856 | { | ||
5857 | unsigned int old_ctl, pin_ctl; | ||
5858 | |||
5859 | pin_ctl = snd_hda_codec_read(codec, nid, | ||
5860 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
5861 | |||
5862 | if (pin_ctl & AC_PINCTL_IN_EN) { | ||
5863 | /* | ||
5864 | * we need to check the current set-up direction of | ||
5865 | * shared input pins since they can be switched via | ||
5866 | * "xxx as Output" mixer switch | ||
5867 | */ | ||
5868 | struct sigmatel_spec *spec = codec->spec; | ||
5869 | if (nid == spec->line_switch || nid == spec->mic_switch) | ||
5870 | return; | ||
5871 | } | ||
5872 | |||
5873 | old_ctl = pin_ctl; | ||
5874 | /* if setting pin direction bits, clear the current | ||
5875 | direction bits first */ | ||
5876 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | ||
5877 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | ||
5878 | |||
5879 | pin_ctl |= flag; | ||
5880 | if (old_ctl != pin_ctl) | ||
5881 | snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl); | ||
5882 | } | ||
5883 | |||
5884 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
5885 | unsigned int flag) | ||
5886 | { | ||
5887 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
5888 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
5889 | if (pin_ctl & flag) | ||
5890 | snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl & ~flag); | ||
5891 | } | ||
5892 | |||
5893 | static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | ||
5894 | { | ||
5895 | if (!nid) | ||
5896 | return 0; | ||
5897 | return snd_hda_jack_detect(codec, nid); | ||
5898 | } | ||
5899 | |||
5900 | static void stac92xx_line_out_detect(struct hda_codec *codec, | ||
5901 | int presence) | ||
5902 | { | ||
5903 | struct sigmatel_spec *spec = codec->spec; | ||
5904 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5905 | int i; | ||
5906 | |||
5907 | if (cfg->speaker_outs == 0) | ||
5908 | return; | ||
5909 | |||
5910 | for (i = 0; i < cfg->line_outs; i++) { | ||
5911 | if (presence) | ||
5912 | break; | ||
5913 | presence = get_pin_presence(codec, cfg->line_out_pins[i]); | ||
5914 | if (presence) { | ||
5915 | unsigned int pinctl; | ||
5916 | pinctl = snd_hda_codec_read(codec, | ||
5917 | cfg->line_out_pins[i], 0, | ||
5918 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5919 | if (pinctl & AC_PINCTL_IN_EN) | ||
5920 | presence = 0; /* mic- or line-input */ | ||
5921 | } | ||
5922 | } | ||
5923 | |||
5924 | if (presence) { | ||
5925 | /* disable speakers */ | ||
5926 | for (i = 0; i < cfg->speaker_outs; i++) | ||
5927 | stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], | ||
5928 | AC_PINCTL_OUT_EN); | ||
5929 | if (spec->eapd_mask && spec->eapd_switch) | ||
5930 | stac_gpio_set(codec, spec->gpio_mask, | ||
5931 | spec->gpio_dir, spec->gpio_data & | ||
5932 | ~spec->eapd_mask); | ||
5933 | } else { | ||
5934 | /* enable speakers */ | ||
5935 | for (i = 0; i < cfg->speaker_outs; i++) | ||
5936 | stac92xx_set_pinctl(codec, cfg->speaker_pins[i], | ||
5937 | AC_PINCTL_OUT_EN); | ||
5938 | if (spec->eapd_mask && spec->eapd_switch) | ||
5939 | stac_gpio_set(codec, spec->gpio_mask, | ||
5940 | spec->gpio_dir, spec->gpio_data | | ||
5941 | spec->eapd_mask); | ||
5942 | } | ||
5943 | } | ||
5944 | |||
5945 | /* return non-zero if the hp-pin of the given array index isn't | ||
5946 | * a jack-detection target | ||
5947 | */ | ||
5948 | static int no_hp_sensing(struct sigmatel_spec *spec, int i) | ||
5949 | { | ||
5950 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5951 | |||
5952 | /* ignore sensing of shared line and mic jacks */ | ||
5953 | if (cfg->hp_pins[i] == spec->line_switch) | ||
5954 | return 1; | ||
5955 | if (cfg->hp_pins[i] == spec->mic_switch) | ||
5956 | return 1; | ||
5957 | /* ignore if the pin is set as line-out */ | ||
5958 | if (cfg->hp_pins[i] == spec->hp_switch) | ||
5959 | return 1; | ||
5960 | return 0; | ||
5961 | } | ||
5962 | |||
5963 | static void stac92xx_hp_detect(struct hda_codec *codec) | ||
5964 | { | ||
5965 | struct sigmatel_spec *spec = codec->spec; | ||
5966 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5967 | int i, presence; | ||
5968 | |||
5969 | presence = 0; | ||
5970 | if (spec->gpio_mute) | ||
5971 | presence = !(snd_hda_codec_read(codec, codec->afg, 0, | ||
5972 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); | ||
5973 | |||
5974 | for (i = 0; i < cfg->hp_outs; i++) { | ||
5975 | if (presence) | ||
5976 | break; | ||
5977 | if (no_hp_sensing(spec, i)) | ||
5978 | continue; | ||
5979 | presence = get_pin_presence(codec, cfg->hp_pins[i]); | ||
5980 | if (presence) { | ||
5981 | unsigned int pinctl; | ||
5982 | pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
5983 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5984 | if (pinctl & AC_PINCTL_IN_EN) | ||
5985 | presence = 0; /* mic- or line-input */ | ||
5986 | } | ||
5987 | } | ||
5988 | |||
5989 | if (presence) { | ||
5990 | /* disable lineouts */ | ||
5991 | if (spec->hp_switch) | ||
5992 | stac92xx_reset_pinctl(codec, spec->hp_switch, | ||
5993 | AC_PINCTL_OUT_EN); | ||
5994 | for (i = 0; i < cfg->line_outs; i++) | ||
5995 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | ||
5996 | AC_PINCTL_OUT_EN); | ||
5997 | } else { | ||
5998 | /* enable lineouts */ | ||
5999 | if (spec->hp_switch) | ||
6000 | stac92xx_set_pinctl(codec, spec->hp_switch, | ||
6001 | AC_PINCTL_OUT_EN); | ||
6002 | for (i = 0; i < cfg->line_outs; i++) | ||
6003 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | ||
6004 | AC_PINCTL_OUT_EN); | ||
6005 | } | ||
6006 | stac92xx_line_out_detect(codec, presence); | ||
6007 | /* toggle hp outs */ | ||
6008 | for (i = 0; i < cfg->hp_outs; i++) { | ||
6009 | unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; | ||
6010 | if (no_hp_sensing(spec, i)) | ||
6011 | continue; | ||
6012 | if (1 /*presence*/) | ||
6013 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); | ||
6014 | #if 0 /* FIXME */ | ||
6015 | /* Resetting the pinctl like below may lead to (a sort of) regressions | ||
6016 | * on some devices since they use the HP pin actually for line/speaker | ||
6017 | * outs although the default pin config shows a different pin (that is | ||
6018 | * wrong and useless). | ||
6019 | * | ||
6020 | * So, it's basically a problem of default pin configs, likely a BIOS issue. | ||
6021 | * But, disabling the code below just works around it, and I'm too tired of | ||
6022 | * bug reports with such devices... | ||
6023 | */ | ||
6024 | else | ||
6025 | stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val); | ||
6026 | #endif /* FIXME */ | ||
6027 | } | ||
6028 | } | ||
6029 | |||
6030 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | ||
6031 | int enable) | ||
6032 | { | ||
6033 | struct sigmatel_spec *spec = codec->spec; | ||
6034 | unsigned int idx, val; | ||
6035 | |||
6036 | for (idx = 0; idx < spec->num_pwrs; idx++) { | ||
6037 | if (spec->pwr_nids[idx] == nid) | ||
6038 | break; | ||
6039 | } | ||
6040 | if (idx >= spec->num_pwrs) | ||
6041 | return; | ||
6042 | |||
6043 | idx = 1 << idx; | ||
6044 | |||
6045 | val = spec->power_map_bits; | ||
6046 | if (enable) | ||
6047 | val &= ~idx; | ||
6048 | else | ||
6049 | val |= idx; | ||
6050 | |||
6051 | /* power down unused output ports */ | ||
6052 | if (val != spec->power_map_bits) { | ||
6053 | spec->power_map_bits = val; | ||
6054 | snd_hda_codec_write(codec, codec->afg, 0, | ||
6055 | AC_VERB_IDT_SET_POWER_MAP, val); | ||
6056 | } | ||
6057 | } | ||
6058 | |||
6059 | static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | ||
6060 | { | ||
6061 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); | ||
6062 | } | ||
6063 | |||
6064 | /* get the pin connection (fixed, none, etc) */ | ||
6065 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
6066 | { | ||
6067 | struct sigmatel_spec *spec = codec->spec; | ||
6068 | unsigned int cfg; | ||
6069 | |||
6070 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
6071 | return get_defcfg_connect(cfg); | ||
6072 | } | ||
6073 | |||
6074 | static int stac92xx_connected_ports(struct hda_codec *codec, | ||
6075 | const hda_nid_t *nids, int num_nids) | ||
6076 | { | ||
6077 | struct sigmatel_spec *spec = codec->spec; | ||
6078 | int idx, num; | ||
6079 | unsigned int def_conf; | ||
6080 | |||
6081 | for (num = 0; num < num_nids; num++) { | ||
6082 | for (idx = 0; idx < spec->num_pins; idx++) | ||
6083 | if (spec->pin_nids[idx] == nids[num]) | ||
6084 | break; | ||
6085 | if (idx >= spec->num_pins) | ||
6086 | break; | ||
6087 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
6088 | if (def_conf == AC_JACK_PORT_NONE) | ||
6089 | break; | ||
6090 | } | ||
6091 | return num; | ||
6092 | } | ||
6093 | |||
6094 | static void stac92xx_mic_detect(struct hda_codec *codec) | ||
6095 | { | ||
6096 | struct sigmatel_spec *spec = codec->spec; | ||
6097 | struct sigmatel_mic_route *mic; | ||
6098 | |||
6099 | if (get_pin_presence(codec, spec->ext_mic.pin)) | ||
6100 | mic = &spec->ext_mic; | ||
6101 | else if (get_pin_presence(codec, spec->dock_mic.pin)) | ||
6102 | mic = &spec->dock_mic; | ||
6103 | else | ||
6104 | mic = &spec->int_mic; | ||
6105 | if (mic->dmux_idx >= 0) | ||
6106 | snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, | ||
6107 | AC_VERB_SET_CONNECT_SEL, | ||
6108 | mic->dmux_idx); | ||
6109 | if (mic->mux_idx >= 0) | ||
6110 | snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, | ||
6111 | AC_VERB_SET_CONNECT_SEL, | ||
6112 | mic->mux_idx); | ||
6113 | } | ||
6114 | |||
6115 | static void handle_unsol_event(struct hda_codec *codec, | ||
6116 | struct hda_jack_tbl *event) | ||
6117 | { | ||
6118 | struct sigmatel_spec *spec = codec->spec; | ||
6119 | int data; | ||
6120 | |||
6121 | switch (event->action) { | ||
6122 | case STAC_HP_EVENT: | ||
6123 | case STAC_LO_EVENT: | ||
6124 | stac92xx_hp_detect(codec); | ||
6125 | break; | ||
6126 | case STAC_MIC_EVENT: | ||
6127 | stac92xx_mic_detect(codec); | ||
6128 | break; | ||
6129 | } | ||
6130 | |||
6131 | switch (event->action) { | ||
6132 | case STAC_HP_EVENT: | ||
6133 | case STAC_LO_EVENT: | ||
6134 | case STAC_MIC_EVENT: | ||
6135 | case STAC_INSERT_EVENT: | ||
6136 | case STAC_PWR_EVENT: | ||
6137 | if (spec->num_pwrs > 0) | ||
6138 | stac92xx_pin_sense(codec, event->nid); | ||
6139 | |||
6140 | switch (codec->subsystem_id) { | ||
6141 | case 0x103c308f: | ||
6142 | if (event->nid == 0xb) { | ||
6143 | int pin = AC_PINCTL_IN_EN; | ||
6144 | |||
6145 | if (get_pin_presence(codec, 0xa) | ||
6146 | && get_pin_presence(codec, 0xb)) | ||
6147 | pin |= AC_PINCTL_VREF_80; | ||
6148 | if (!get_pin_presence(codec, 0xb)) | ||
6149 | pin |= AC_PINCTL_VREF_80; | ||
6150 | |||
6151 | /* toggle VREF state based on mic + hp pin | ||
6152 | * status | ||
6153 | */ | ||
6154 | stac92xx_auto_set_pinctl(codec, 0x0a, pin); | ||
6155 | } | ||
6156 | } | ||
6157 | break; | ||
6158 | case STAC_VREF_EVENT: | ||
6159 | data = snd_hda_codec_read(codec, codec->afg, 0, | ||
6160 | AC_VERB_GET_GPIO_DATA, 0); | ||
6161 | /* toggle VREF state based on GPIOx status */ | ||
6162 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | ||
6163 | !!(data & (1 << event->private_data))); | ||
6164 | break; | ||
6165 | } | ||
6166 | } | ||
6167 | |||
6168 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | ||
6169 | { | ||
6170 | struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid); | ||
6171 | if (!event) | ||
6172 | return; | ||
6173 | handle_unsol_event(codec, event); | ||
6174 | } | ||
6175 | |||
6176 | static void set_hp_led_gpio(struct hda_codec *codec) | ||
6177 | { | ||
6178 | struct sigmatel_spec *spec = codec->spec; | ||
6179 | unsigned int gpio; | ||
6180 | |||
6181 | if (spec->gpio_led) | ||
6182 | return; | ||
6183 | |||
6184 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); | ||
6185 | gpio &= AC_GPIO_IO_COUNT; | ||
6186 | if (gpio > 3) | ||
6187 | spec->gpio_led = 0x08; /* GPIO 3 */ | ||
6188 | else | ||
6189 | spec->gpio_led = 0x01; /* GPIO 0 */ | ||
6190 | } | ||
6191 | |||
6192 | /* | ||
6193 | * This method searches for the mute LED GPIO configuration | ||
6194 | * provided as OEM string in SMBIOS. The format of that string | ||
6195 | * is HP_Mute_LED_P_G or HP_Mute_LED_P | ||
6196 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) | ||
6197 | * that corresponds to the NOT muted state of the master volume | ||
6198 | * and G is the index of the GPIO to use as the mute LED control (0..9) | ||
6199 | * If _G portion is missing it is assigned based on the codec ID | ||
6200 | * | ||
6201 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) | ||
6202 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings | ||
6203 | * | ||
6204 | * | ||
6205 | * The dv-series laptops don't seem to have the HP_Mute_LED* strings in | ||
6206 | * SMBIOS - at least the ones I have seen do not have them - which include | ||
6207 | * my own system (HP Pavilion dv6-1110ax) and my cousin's | ||
6208 | * HP Pavilion dv9500t CTO. | ||
6209 | * Need more information on whether it is true across the entire series. | ||
6210 | * -- kunal | ||
6211 | */ | ||
6212 | static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) | ||
6213 | { | ||
6214 | struct sigmatel_spec *spec = codec->spec; | ||
6215 | const struct dmi_device *dev = NULL; | ||
6216 | |||
6217 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | ||
6218 | get_int_hint(codec, "gpio_led_polarity", | ||
6219 | &spec->gpio_led_polarity); | ||
6220 | return 1; | ||
6221 | } | ||
6222 | |||
6223 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { | ||
6224 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", | ||
6225 | &spec->gpio_led_polarity, | ||
6226 | &spec->gpio_led) == 2) { | ||
6227 | unsigned int max_gpio; | ||
6228 | max_gpio = snd_hda_param_read(codec, codec->afg, | ||
6229 | AC_PAR_GPIO_CAP); | ||
6230 | max_gpio &= AC_GPIO_IO_COUNT; | ||
6231 | if (spec->gpio_led < max_gpio) | ||
6232 | spec->gpio_led = 1 << spec->gpio_led; | ||
6233 | else | ||
6234 | spec->vref_mute_led_nid = spec->gpio_led; | ||
6235 | return 1; | ||
6236 | } | ||
6237 | if (sscanf(dev->name, "HP_Mute_LED_%d", | ||
6238 | &spec->gpio_led_polarity) == 1) { | ||
6239 | set_hp_led_gpio(codec); | ||
6240 | return 1; | ||
6241 | } | ||
6242 | /* BIOS bug: unfilled OEM string */ | ||
6243 | if (strstr(dev->name, "HP_Mute_LED_P_G")) { | ||
6244 | set_hp_led_gpio(codec); | ||
6245 | if (default_polarity >= 0) | ||
6246 | spec->gpio_led_polarity = default_polarity; | ||
6247 | else | ||
6248 | spec->gpio_led_polarity = 1; | ||
6249 | return 1; | ||
6250 | } | ||
6251 | } | ||
6252 | |||
6253 | /* | ||
6254 | * Fallback case - if we don't find the DMI strings, | ||
6255 | * we statically set the GPIO - if not a B-series system | ||
6256 | * and default polarity is provided | ||
6257 | */ | ||
6258 | if (!hp_blike_system(codec->subsystem_id) && | ||
6259 | (default_polarity == 0 || default_polarity == 1)) { | ||
6260 | set_hp_led_gpio(codec); | ||
6261 | spec->gpio_led_polarity = default_polarity; | ||
6262 | return 1; | ||
6263 | } | ||
6264 | return 0; | ||
6265 | } | ||
6266 | |||
6267 | static int hp_blike_system(u32 subsystem_id) | ||
6268 | { | ||
6269 | switch (subsystem_id) { | ||
6270 | case 0x103c1520: | ||
6271 | case 0x103c1521: | ||
6272 | case 0x103c1523: | ||
6273 | case 0x103c1524: | ||
6274 | case 0x103c1525: | ||
6275 | case 0x103c1722: | ||
6276 | case 0x103c1723: | ||
6277 | case 0x103c1724: | ||
6278 | case 0x103c1725: | ||
6279 | case 0x103c1726: | ||
6280 | case 0x103c1727: | ||
6281 | case 0x103c1728: | ||
6282 | case 0x103c1729: | ||
6283 | case 0x103c172a: | ||
6284 | case 0x103c172b: | ||
6285 | case 0x103c307e: | ||
6286 | case 0x103c307f: | ||
6287 | case 0x103c3080: | ||
6288 | case 0x103c3081: | ||
6289 | case 0x103c7007: | ||
6290 | case 0x103c7008: | ||
6291 | return 1; | ||
6292 | } | ||
6293 | return 0; | ||
6294 | } | ||
6295 | |||
6296 | #ifdef CONFIG_PROC_FS | 3540 | #ifdef CONFIG_PROC_FS |
6297 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, | 3541 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, |
6298 | struct hda_codec *codec, hda_nid_t nid) | 3542 | struct hda_codec *codec, hda_nid_t nid) |
@@ -6341,24 +3585,22 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, | |||
6341 | #endif | 3585 | #endif |
6342 | 3586 | ||
6343 | #ifdef CONFIG_PM | 3587 | #ifdef CONFIG_PM |
6344 | static int stac92xx_resume(struct hda_codec *codec) | 3588 | static int stac_resume(struct hda_codec *codec) |
6345 | { | 3589 | { |
6346 | stac92xx_init(codec); | 3590 | codec->patch_ops.init(codec); |
6347 | snd_hda_codec_resume_amp(codec); | 3591 | snd_hda_codec_resume_amp(codec); |
6348 | snd_hda_codec_resume_cache(codec); | 3592 | snd_hda_codec_resume_cache(codec); |
6349 | /* fake event to set up pins again to override cached values */ | ||
6350 | stac_fake_hp_events(codec); | ||
6351 | return 0; | 3593 | return 0; |
6352 | } | 3594 | } |
6353 | 3595 | ||
6354 | static int stac92xx_suspend(struct hda_codec *codec) | 3596 | static int stac_suspend(struct hda_codec *codec) |
6355 | { | 3597 | { |
6356 | stac92xx_shutup(codec); | 3598 | stac_shutup(codec); |
6357 | return 0; | 3599 | return 0; |
6358 | } | 3600 | } |
6359 | 3601 | ||
6360 | static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3602 | static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
6361 | unsigned int power_state) | 3603 | unsigned int power_state) |
6362 | { | 3604 | { |
6363 | unsigned int afg_power_state = power_state; | 3605 | unsigned int afg_power_state = power_state; |
6364 | struct sigmatel_spec *spec = codec->spec; | 3606 | struct sigmatel_spec *spec = codec->spec; |
@@ -6378,64 +3620,34 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
6378 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 3620 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); |
6379 | } | 3621 | } |
6380 | #else | 3622 | #else |
6381 | #define stac92xx_suspend NULL | 3623 | #define stac_suspend NULL |
6382 | #define stac92xx_resume NULL | 3624 | #define stac_resume NULL |
6383 | #define stac92xx_set_power_state NULL | 3625 | #define stac_set_power_state NULL |
6384 | #endif /* CONFIG_PM */ | 3626 | #endif /* CONFIG_PM */ |
6385 | 3627 | ||
6386 | /* update mute-LED accoring to the master switch */ | 3628 | static const struct hda_codec_ops stac_patch_ops = { |
6387 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) | 3629 | .build_controls = snd_hda_gen_build_controls, |
6388 | { | 3630 | .build_pcms = snd_hda_gen_build_pcms, |
6389 | struct sigmatel_spec *spec = codec->spec; | 3631 | .init = stac_init, |
6390 | int muted = !enabled; | 3632 | .free = stac_free, |
6391 | |||
6392 | if (!spec->gpio_led) | ||
6393 | return; | ||
6394 | |||
6395 | /* LED state is inverted on these systems */ | ||
6396 | if (spec->gpio_led_polarity) | ||
6397 | muted = !muted; | ||
6398 | |||
6399 | if (!spec->vref_mute_led_nid) { | ||
6400 | if (muted) | ||
6401 | spec->gpio_data |= spec->gpio_led; | ||
6402 | else | ||
6403 | spec->gpio_data &= ~spec->gpio_led; | ||
6404 | stac_gpio_set(codec, spec->gpio_mask, | ||
6405 | spec->gpio_dir, spec->gpio_data); | ||
6406 | } else { | ||
6407 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; | ||
6408 | stac_vrefout_set(codec, spec->vref_mute_led_nid, | ||
6409 | spec->vref_led); | ||
6410 | } | ||
6411 | } | ||
6412 | |||
6413 | static const struct hda_codec_ops stac92xx_patch_ops = { | ||
6414 | .build_controls = stac92xx_build_controls, | ||
6415 | .build_pcms = stac92xx_build_pcms, | ||
6416 | .init = stac92xx_init, | ||
6417 | .free = stac92xx_free, | ||
6418 | .unsol_event = snd_hda_jack_unsol_event, | 3633 | .unsol_event = snd_hda_jack_unsol_event, |
6419 | #ifdef CONFIG_PM | 3634 | #ifdef CONFIG_PM |
6420 | .suspend = stac92xx_suspend, | 3635 | .suspend = stac_suspend, |
6421 | .resume = stac92xx_resume, | 3636 | .resume = stac_resume, |
6422 | #endif | 3637 | #endif |
6423 | .reboot_notify = stac92xx_shutup, | 3638 | .reboot_notify = stac_shutup, |
6424 | }; | 3639 | }; |
6425 | 3640 | ||
6426 | static int alloc_stac_spec(struct hda_codec *codec, int num_pins, | 3641 | static int alloc_stac_spec(struct hda_codec *codec) |
6427 | const hda_nid_t *pin_nids) | ||
6428 | { | 3642 | { |
6429 | struct sigmatel_spec *spec; | 3643 | struct sigmatel_spec *spec; |
6430 | 3644 | ||
6431 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3645 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
6432 | if (!spec) | 3646 | if (!spec) |
6433 | return -ENOMEM; | 3647 | return -ENOMEM; |
3648 | snd_hda_gen_spec_init(&spec->gen); | ||
6434 | codec->spec = spec; | 3649 | codec->spec = spec; |
6435 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ | 3650 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ |
6436 | spec->num_pins = num_pins; | ||
6437 | spec->pin_nids = pin_nids; | ||
6438 | snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); | ||
6439 | return 0; | 3651 | return 0; |
6440 | } | 3652 | } |
6441 | 3653 | ||
@@ -6444,40 +3656,28 @@ static int patch_stac9200(struct hda_codec *codec) | |||
6444 | struct sigmatel_spec *spec; | 3656 | struct sigmatel_spec *spec; |
6445 | int err; | 3657 | int err; |
6446 | 3658 | ||
6447 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids), | 3659 | err = alloc_stac_spec(codec); |
6448 | stac9200_pin_nids); | ||
6449 | if (err < 0) | 3660 | if (err < 0) |
6450 | return err; | 3661 | return err; |
6451 | 3662 | ||
6452 | spec = codec->spec; | 3663 | spec = codec->spec; |
6453 | spec->linear_tone_beep = 1; | 3664 | spec->linear_tone_beep = 1; |
3665 | spec->gen.own_eapd_ctl = 1; | ||
6454 | 3666 | ||
6455 | snd_hda_pick_fixup(codec, stac9200_models, stac9200_fixup_tbl, | 3667 | codec->patch_ops = stac_patch_ops; |
6456 | stac9200_fixups); | ||
6457 | 3668 | ||
6458 | spec->multiout.max_channels = 2; | ||
6459 | spec->multiout.num_dacs = 1; | ||
6460 | spec->multiout.dac_nids = stac9200_dac_nids; | ||
6461 | spec->adc_nids = stac9200_adc_nids; | ||
6462 | spec->mux_nids = stac9200_mux_nids; | ||
6463 | spec->num_muxes = 1; | ||
6464 | spec->num_dmics = 0; | ||
6465 | spec->num_adcs = 1; | ||
6466 | spec->num_pwrs = 0; | ||
6467 | snd_hda_add_verbs(codec, stac9200_eapd_init); | 3669 | snd_hda_add_verbs(codec, stac9200_eapd_init); |
6468 | 3670 | ||
6469 | spec->mixer = stac9200_mixer; | 3671 | snd_hda_pick_fixup(codec, stac9200_models, stac9200_fixup_tbl, |
6470 | 3672 | stac9200_fixups); | |
6471 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3673 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
6472 | 3674 | ||
6473 | err = stac9200_parse_auto_config(codec); | 3675 | err = stac_parse_auto_config(codec); |
6474 | if (err < 0) { | 3676 | if (err < 0) { |
6475 | stac92xx_free(codec); | 3677 | stac_free(codec); |
6476 | return err; | 3678 | return err; |
6477 | } | 3679 | } |
6478 | 3680 | ||
6479 | codec->patch_ops = stac92xx_patch_ops; | ||
6480 | |||
6481 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 3681 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
6482 | 3682 | ||
6483 | return 0; | 3683 | return 0; |
@@ -6488,56 +3688,28 @@ static int patch_stac925x(struct hda_codec *codec) | |||
6488 | struct sigmatel_spec *spec; | 3688 | struct sigmatel_spec *spec; |
6489 | int err; | 3689 | int err; |
6490 | 3690 | ||
6491 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids), | 3691 | err = alloc_stac_spec(codec); |
6492 | stac925x_pin_nids); | ||
6493 | if (err < 0) | 3692 | if (err < 0) |
6494 | return err; | 3693 | return err; |
6495 | 3694 | ||
6496 | spec = codec->spec; | 3695 | spec = codec->spec; |
6497 | spec->linear_tone_beep = 1; | 3696 | spec->linear_tone_beep = 1; |
3697 | spec->gen.own_eapd_ctl = 1; | ||
6498 | 3698 | ||
6499 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, | 3699 | codec->patch_ops = stac_patch_ops; |
6500 | stac925x_fixups); | ||
6501 | |||
6502 | spec->multiout.max_channels = 2; | ||
6503 | spec->multiout.num_dacs = 1; | ||
6504 | spec->multiout.dac_nids = stac925x_dac_nids; | ||
6505 | spec->adc_nids = stac925x_adc_nids; | ||
6506 | spec->mux_nids = stac925x_mux_nids; | ||
6507 | spec->num_muxes = 1; | ||
6508 | spec->num_adcs = 1; | ||
6509 | spec->num_pwrs = 0; | ||
6510 | switch (codec->vendor_id) { | ||
6511 | case 0x83847632: /* STAC9202 */ | ||
6512 | case 0x83847633: /* STAC9202D */ | ||
6513 | case 0x83847636: /* STAC9251 */ | ||
6514 | case 0x83847637: /* STAC9251D */ | ||
6515 | spec->num_dmics = STAC925X_NUM_DMICS; | ||
6516 | spec->dmic_nids = stac925x_dmic_nids; | ||
6517 | spec->num_dmuxes = ARRAY_SIZE(stac925x_dmux_nids); | ||
6518 | spec->dmux_nids = stac925x_dmux_nids; | ||
6519 | break; | ||
6520 | default: | ||
6521 | spec->num_dmics = 0; | ||
6522 | break; | ||
6523 | } | ||
6524 | 3700 | ||
6525 | snd_hda_add_verbs(codec, stac925x_core_init); | 3701 | snd_hda_add_verbs(codec, stac925x_core_init); |
6526 | spec->mixer = stac925x_mixer; | ||
6527 | spec->num_caps = 1; | ||
6528 | spec->capvols = stac925x_capvols; | ||
6529 | spec->capsws = stac925x_capsws; | ||
6530 | 3702 | ||
3703 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, | ||
3704 | stac925x_fixups); | ||
6531 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3705 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
6532 | 3706 | ||
6533 | err = stac92xx_parse_auto_config(codec); | 3707 | err = stac_parse_auto_config(codec); |
6534 | if (err < 0) { | 3708 | if (err < 0) { |
6535 | stac92xx_free(codec); | 3709 | stac_free(codec); |
6536 | return err; | 3710 | return err; |
6537 | } | 3711 | } |
6538 | 3712 | ||
6539 | codec->patch_ops = stac92xx_patch_ops; | ||
6540 | |||
6541 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 3713 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
6542 | 3714 | ||
6543 | return 0; | 3715 | return 0; |
@@ -6546,86 +3718,66 @@ static int patch_stac925x(struct hda_codec *codec) | |||
6546 | static int patch_stac92hd73xx(struct hda_codec *codec) | 3718 | static int patch_stac92hd73xx(struct hda_codec *codec) |
6547 | { | 3719 | { |
6548 | struct sigmatel_spec *spec; | 3720 | struct sigmatel_spec *spec; |
6549 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; | ||
6550 | int err; | 3721 | int err; |
6551 | int num_dacs; | 3722 | int num_dacs; |
6552 | 3723 | ||
6553 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids), | 3724 | err = alloc_stac_spec(codec); |
6554 | stac92hd73xx_pin_nids); | ||
6555 | if (err < 0) | 3725 | if (err < 0) |
6556 | return err; | 3726 | return err; |
6557 | 3727 | ||
6558 | spec = codec->spec; | 3728 | spec = codec->spec; |
6559 | spec->linear_tone_beep = 0; | 3729 | spec->linear_tone_beep = 0; |
6560 | codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; | ||
6561 | |||
6562 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, | ||
6563 | stac92hd73xx_fixups); | ||
6564 | |||
6565 | num_dacs = snd_hda_get_connections(codec, 0x0a, | ||
6566 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | ||
6567 | 3730 | ||
3731 | num_dacs = snd_hda_get_num_conns(codec, 0x0a) - 1; | ||
6568 | if (num_dacs < 3 || num_dacs > 5) { | 3732 | if (num_dacs < 3 || num_dacs > 5) { |
6569 | printk(KERN_WARNING "hda_codec: Could not determine " | 3733 | printk(KERN_WARNING "hda_codec: Could not determine " |
6570 | "number of channels defaulting to DAC count\n"); | 3734 | "number of channels defaulting to DAC count\n"); |
6571 | num_dacs = STAC92HD73_DAC_COUNT; | 3735 | num_dacs = 5; |
6572 | } | 3736 | } |
6573 | 3737 | ||
6574 | switch (num_dacs) { | 3738 | switch (num_dacs) { |
6575 | case 0x3: /* 6 Channel */ | 3739 | case 0x3: /* 6 Channel */ |
6576 | spec->aloopback_ctl = stac92hd73xx_6ch_loopback; | 3740 | spec->aloopback_ctl = &stac92hd73xx_6ch_loopback; |
6577 | break; | 3741 | break; |
6578 | case 0x4: /* 8 Channel */ | 3742 | case 0x4: /* 8 Channel */ |
6579 | spec->aloopback_ctl = stac92hd73xx_8ch_loopback; | 3743 | spec->aloopback_ctl = &stac92hd73xx_8ch_loopback; |
6580 | break; | 3744 | break; |
6581 | case 0x5: /* 10 Channel */ | 3745 | case 0x5: /* 10 Channel */ |
6582 | spec->aloopback_ctl = stac92hd73xx_10ch_loopback; | 3746 | spec->aloopback_ctl = &stac92hd73xx_10ch_loopback; |
6583 | break; | 3747 | break; |
6584 | } | 3748 | } |
6585 | spec->multiout.dac_nids = spec->dac_nids; | ||
6586 | 3749 | ||
6587 | spec->aloopback_mask = 0x01; | 3750 | spec->aloopback_mask = 0x01; |
6588 | spec->aloopback_shift = 8; | 3751 | spec->aloopback_shift = 8; |
6589 | 3752 | ||
6590 | spec->digbeep_nid = 0x1c; | 3753 | spec->digbeep_nid = 0x1c; |
6591 | spec->mux_nids = stac92hd73xx_mux_nids; | ||
6592 | spec->adc_nids = stac92hd73xx_adc_nids; | ||
6593 | spec->dmic_nids = stac92hd73xx_dmic_nids; | ||
6594 | spec->dmux_nids = stac92hd73xx_dmux_nids; | ||
6595 | spec->smux_nids = stac92hd73xx_smux_nids; | ||
6596 | |||
6597 | spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); | ||
6598 | spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); | ||
6599 | spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); | ||
6600 | |||
6601 | spec->num_caps = STAC92HD73XX_NUM_CAPS; | ||
6602 | spec->capvols = stac92hd73xx_capvols; | ||
6603 | spec->capsws = stac92hd73xx_capsws; | ||
6604 | 3754 | ||
6605 | /* GPIO0 High = Enable EAPD */ | 3755 | /* GPIO0 High = Enable EAPD */ |
6606 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 3756 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
6607 | spec->gpio_data = 0x01; | 3757 | spec->gpio_data = 0x01; |
6608 | 3758 | ||
6609 | spec->num_dmics = STAC92HD73XX_NUM_DMICS; | ||
6610 | spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); | ||
6611 | spec->eapd_switch = 1; | 3759 | spec->eapd_switch = 1; |
6612 | 3760 | ||
6613 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); | 3761 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); |
6614 | spec->pwr_nids = stac92hd73xx_pwr_nids; | 3762 | spec->pwr_nids = stac92hd73xx_pwr_nids; |
6615 | 3763 | ||
3764 | spec->gen.own_eapd_ctl = 1; | ||
3765 | |||
3766 | codec->patch_ops = stac_patch_ops; | ||
3767 | |||
3768 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, | ||
3769 | stac92hd73xx_fixups); | ||
6616 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3770 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
6617 | 3771 | ||
6618 | if (!spec->volknob_init) | 3772 | if (!spec->volknob_init) |
6619 | snd_hda_add_verbs(codec, stac92hd73xx_core_init); | 3773 | snd_hda_add_verbs(codec, stac92hd73xx_core_init); |
6620 | 3774 | ||
6621 | err = stac92xx_parse_auto_config(codec); | 3775 | err = stac_parse_auto_config(codec); |
6622 | if (err < 0) { | 3776 | if (err < 0) { |
6623 | stac92xx_free(codec); | 3777 | stac_free(codec); |
6624 | return err; | 3778 | return err; |
6625 | } | 3779 | } |
6626 | 3780 | ||
6627 | codec->patch_ops = stac92xx_patch_ops; | ||
6628 | |||
6629 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 3781 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
6630 | 3782 | ||
6631 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 3783 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
@@ -6633,145 +3785,6 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
6633 | return 0; | 3785 | return 0; |
6634 | } | 3786 | } |
6635 | 3787 | ||
6636 | static int hp_bnb2011_with_dock(struct hda_codec *codec) | ||
6637 | { | ||
6638 | if (codec->vendor_id != 0x111d7605 && | ||
6639 | codec->vendor_id != 0x111d76d1) | ||
6640 | return 0; | ||
6641 | |||
6642 | switch (codec->subsystem_id) { | ||
6643 | case 0x103c1618: | ||
6644 | case 0x103c1619: | ||
6645 | case 0x103c161a: | ||
6646 | case 0x103c161b: | ||
6647 | case 0x103c161c: | ||
6648 | case 0x103c161d: | ||
6649 | case 0x103c161e: | ||
6650 | case 0x103c161f: | ||
6651 | |||
6652 | case 0x103c162a: | ||
6653 | case 0x103c162b: | ||
6654 | |||
6655 | case 0x103c1630: | ||
6656 | case 0x103c1631: | ||
6657 | |||
6658 | case 0x103c1633: | ||
6659 | case 0x103c1634: | ||
6660 | case 0x103c1635: | ||
6661 | |||
6662 | case 0x103c3587: | ||
6663 | case 0x103c3588: | ||
6664 | case 0x103c3589: | ||
6665 | case 0x103c358a: | ||
6666 | |||
6667 | case 0x103c3667: | ||
6668 | case 0x103c3668: | ||
6669 | case 0x103c3669: | ||
6670 | |||
6671 | return 1; | ||
6672 | } | ||
6673 | return 0; | ||
6674 | } | ||
6675 | |||
6676 | static void stac92hd8x_add_pin(struct hda_codec *codec, hda_nid_t nid) | ||
6677 | { | ||
6678 | struct sigmatel_spec *spec = codec->spec; | ||
6679 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
6680 | int i; | ||
6681 | |||
6682 | spec->auto_pin_nids[spec->auto_pin_cnt] = nid; | ||
6683 | spec->auto_pin_cnt++; | ||
6684 | |||
6685 | if (get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
6686 | get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) { | ||
6687 | for (i = 0; i < ARRAY_SIZE(stac92hd83xxx_dmic_nids); i++) { | ||
6688 | if (nid == stac92hd83xxx_dmic_nids[i]) { | ||
6689 | spec->auto_dmic_nids[spec->auto_dmic_cnt] = nid; | ||
6690 | spec->auto_dmic_cnt++; | ||
6691 | } | ||
6692 | } | ||
6693 | } | ||
6694 | } | ||
6695 | |||
6696 | static void stac92hd8x_add_adc(struct hda_codec *codec, hda_nid_t nid) | ||
6697 | { | ||
6698 | struct sigmatel_spec *spec = codec->spec; | ||
6699 | |||
6700 | spec->auto_adc_nids[spec->auto_adc_cnt] = nid; | ||
6701 | spec->auto_adc_cnt++; | ||
6702 | } | ||
6703 | |||
6704 | static void stac92hd8x_add_mux(struct hda_codec *codec, hda_nid_t nid) | ||
6705 | { | ||
6706 | int i, j; | ||
6707 | struct sigmatel_spec *spec = codec->spec; | ||
6708 | |||
6709 | for (i = 0; i < spec->auto_adc_cnt; i++) { | ||
6710 | if (get_connection_index(codec, | ||
6711 | spec->auto_adc_nids[i], nid) >= 0) { | ||
6712 | /* mux and volume for adc_nids[i] */ | ||
6713 | if (!spec->auto_mux_nids[i]) { | ||
6714 | spec->auto_mux_nids[i] = nid; | ||
6715 | /* 92hd codecs capture volume is in mux */ | ||
6716 | spec->auto_capvols[i] = HDA_COMPOSE_AMP_VAL(nid, | ||
6717 | 3, 0, HDA_OUTPUT); | ||
6718 | } | ||
6719 | for (j = 0; j < spec->auto_dmic_cnt; j++) { | ||
6720 | if (get_connection_index(codec, nid, | ||
6721 | spec->auto_dmic_nids[j]) >= 0) { | ||
6722 | /* dmux for adc_nids[i] */ | ||
6723 | if (!spec->auto_dmux_nids[i]) | ||
6724 | spec->auto_dmux_nids[i] = nid; | ||
6725 | break; | ||
6726 | } | ||
6727 | } | ||
6728 | break; | ||
6729 | } | ||
6730 | } | ||
6731 | } | ||
6732 | |||
6733 | static void stac92hd8x_fill_auto_spec(struct hda_codec *codec) | ||
6734 | { | ||
6735 | hda_nid_t nid, end_nid; | ||
6736 | unsigned int wid_caps, wid_type; | ||
6737 | struct sigmatel_spec *spec = codec->spec; | ||
6738 | |||
6739 | end_nid = codec->start_nid + codec->num_nodes; | ||
6740 | |||
6741 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
6742 | wid_caps = get_wcaps(codec, nid); | ||
6743 | wid_type = get_wcaps_type(wid_caps); | ||
6744 | |||
6745 | if (wid_type == AC_WID_PIN) | ||
6746 | stac92hd8x_add_pin(codec, nid); | ||
6747 | |||
6748 | if (wid_type == AC_WID_AUD_IN && !(wid_caps & AC_WCAP_DIGITAL)) | ||
6749 | stac92hd8x_add_adc(codec, nid); | ||
6750 | } | ||
6751 | |||
6752 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
6753 | wid_caps = get_wcaps(codec, nid); | ||
6754 | wid_type = get_wcaps_type(wid_caps); | ||
6755 | |||
6756 | if (wid_type == AC_WID_AUD_SEL) | ||
6757 | stac92hd8x_add_mux(codec, nid); | ||
6758 | } | ||
6759 | |||
6760 | spec->pin_nids = spec->auto_pin_nids; | ||
6761 | spec->num_pins = spec->auto_pin_cnt; | ||
6762 | spec->adc_nids = spec->auto_adc_nids; | ||
6763 | spec->num_adcs = spec->auto_adc_cnt; | ||
6764 | spec->capvols = spec->auto_capvols; | ||
6765 | spec->capsws = spec->auto_capvols; | ||
6766 | spec->num_caps = spec->auto_adc_cnt; | ||
6767 | spec->mux_nids = spec->auto_mux_nids; | ||
6768 | spec->num_muxes = spec->auto_adc_cnt; | ||
6769 | spec->dmux_nids = spec->auto_dmux_nids; | ||
6770 | spec->num_dmuxes = spec->auto_adc_cnt; | ||
6771 | spec->dmic_nids = spec->auto_dmic_nids; | ||
6772 | spec->num_dmics = spec->auto_dmic_cnt; | ||
6773 | } | ||
6774 | |||
6775 | static void stac_setup_gpio(struct hda_codec *codec) | 3788 | static void stac_setup_gpio(struct hda_codec *codec) |
6776 | { | 3789 | { |
6777 | struct sigmatel_spec *spec = codec->spec; | 3790 | struct sigmatel_spec *spec = codec->spec; |
@@ -6783,7 +3796,7 @@ static void stac_setup_gpio(struct hda_codec *codec) | |||
6783 | spec->gpio_data |= spec->gpio_led; | 3796 | spec->gpio_data |= spec->gpio_led; |
6784 | } else { | 3797 | } else { |
6785 | codec->patch_ops.set_power_state = | 3798 | codec->patch_ops.set_power_state = |
6786 | stac92xx_set_power_state; | 3799 | stac_set_power_state; |
6787 | } | 3800 | } |
6788 | } | 3801 | } |
6789 | 3802 | ||
@@ -6792,6 +3805,8 @@ static void stac_setup_gpio(struct hda_codec *codec) | |||
6792 | spec->gpio_dir |= spec->mic_mute_led_gpio; | 3805 | spec->gpio_dir |= spec->mic_mute_led_gpio; |
6793 | spec->mic_mute_led_on = true; | 3806 | spec->mic_mute_led_on = true; |
6794 | spec->gpio_data |= spec->mic_mute_led_gpio; | 3807 | spec->gpio_data |= spec->mic_mute_led_gpio; |
3808 | |||
3809 | spec->gen.capture_switch_hook = stac_capture_led_hook; | ||
6795 | } | 3810 | } |
6796 | } | 3811 | } |
6797 | 3812 | ||
@@ -6800,36 +3815,34 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
6800 | struct sigmatel_spec *spec; | 3815 | struct sigmatel_spec *spec; |
6801 | int err; | 3816 | int err; |
6802 | 3817 | ||
6803 | err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */ | 3818 | err = alloc_stac_spec(codec); |
6804 | if (err < 0) | 3819 | if (err < 0) |
6805 | return err; | 3820 | return err; |
6806 | 3821 | ||
6807 | codec->epss = 0; /* longer delay needed for D3 */ | 3822 | codec->epss = 0; /* longer delay needed for D3 */ |
6808 | stac92hd8x_fill_auto_spec(codec); | ||
6809 | 3823 | ||
6810 | spec = codec->spec; | 3824 | spec = codec->spec; |
6811 | spec->linear_tone_beep = 0; | 3825 | spec->linear_tone_beep = 0; |
6812 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 3826 | spec->gen.own_eapd_ctl = 1; |
3827 | |||
6813 | spec->digbeep_nid = 0x21; | 3828 | spec->digbeep_nid = 0x21; |
6814 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 3829 | spec->pwr_nids = stac92hd83xxx_pwr_nids; |
6815 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 3830 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
6816 | spec->multiout.dac_nids = spec->dac_nids; | 3831 | spec->default_polarity = -1; /* no default cfg */ |
6817 | 3832 | ||
6818 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, | 3833 | codec->patch_ops = stac_patch_ops; |
6819 | stac92hd83xxx_fixups); | ||
6820 | 3834 | ||
6821 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); | 3835 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); |
6822 | spec->default_polarity = -1; /* no default cfg */ | ||
6823 | |||
6824 | codec->patch_ops = stac92xx_patch_ops; | ||
6825 | 3836 | ||
3837 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, | ||
3838 | stac92hd83xxx_fixups); | ||
6826 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3839 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
6827 | 3840 | ||
6828 | stac_setup_gpio(codec); | 3841 | stac_setup_gpio(codec); |
6829 | 3842 | ||
6830 | err = stac92xx_parse_auto_config(codec); | 3843 | err = stac_parse_auto_config(codec); |
6831 | if (err < 0) { | 3844 | if (err < 0) { |
6832 | stac92xx_free(codec); | 3845 | stac_free(codec); |
6833 | return err; | 3846 | return err; |
6834 | } | 3847 | } |
6835 | 3848 | ||
@@ -6840,133 +3853,31 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
6840 | return 0; | 3853 | return 0; |
6841 | } | 3854 | } |
6842 | 3855 | ||
6843 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | ||
6844 | hda_nid_t dig0pin) | ||
6845 | { | ||
6846 | struct sigmatel_spec *spec = codec->spec; | ||
6847 | int idx; | ||
6848 | |||
6849 | for (idx = 0; idx < spec->num_pins; idx++) | ||
6850 | if (spec->pin_nids[idx] == dig0pin) | ||
6851 | break; | ||
6852 | if ((idx + 2) >= spec->num_pins) | ||
6853 | return 0; | ||
6854 | |||
6855 | /* dig1pin case */ | ||
6856 | if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE) | ||
6857 | return 2; | ||
6858 | |||
6859 | /* dig0pin + dig2pin case */ | ||
6860 | if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE) | ||
6861 | return 2; | ||
6862 | if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE) | ||
6863 | return 1; | ||
6864 | else | ||
6865 | return 0; | ||
6866 | } | ||
6867 | |||
6868 | /* HP dv7 bass switch - GPIO5 */ | ||
6869 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | ||
6870 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | ||
6871 | struct snd_ctl_elem_value *ucontrol) | ||
6872 | { | ||
6873 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
6874 | struct sigmatel_spec *spec = codec->spec; | ||
6875 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | ||
6876 | return 0; | ||
6877 | } | ||
6878 | |||
6879 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | ||
6880 | struct snd_ctl_elem_value *ucontrol) | ||
6881 | { | ||
6882 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
6883 | struct sigmatel_spec *spec = codec->spec; | ||
6884 | unsigned int gpio_data; | ||
6885 | |||
6886 | gpio_data = (spec->gpio_data & ~0x20) | | ||
6887 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | ||
6888 | if (gpio_data == spec->gpio_data) | ||
6889 | return 0; | ||
6890 | spec->gpio_data = gpio_data; | ||
6891 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | ||
6892 | return 1; | ||
6893 | } | ||
6894 | |||
6895 | static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | ||
6896 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6897 | .info = stac_hp_bass_gpio_info, | ||
6898 | .get = stac_hp_bass_gpio_get, | ||
6899 | .put = stac_hp_bass_gpio_put, | ||
6900 | }; | ||
6901 | |||
6902 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | ||
6903 | { | ||
6904 | struct sigmatel_spec *spec = codec->spec; | ||
6905 | |||
6906 | if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl, | ||
6907 | "Bass Speaker Playback Switch", 0)) | ||
6908 | return -ENOMEM; | ||
6909 | |||
6910 | spec->gpio_mask |= 0x20; | ||
6911 | spec->gpio_dir |= 0x20; | ||
6912 | spec->gpio_data |= 0x20; | ||
6913 | return 0; | ||
6914 | } | ||
6915 | |||
6916 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 3856 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
6917 | { | 3857 | { |
6918 | struct sigmatel_spec *spec; | 3858 | struct sigmatel_spec *spec; |
6919 | const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; | 3859 | const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; |
6920 | int err; | 3860 | int err; |
6921 | 3861 | ||
6922 | err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS, | 3862 | err = alloc_stac_spec(codec); |
6923 | stac92hd71bxx_pin_nids_4port); | ||
6924 | if (err < 0) | 3863 | if (err < 0) |
6925 | return err; | 3864 | return err; |
6926 | 3865 | ||
6927 | spec = codec->spec; | 3866 | spec = codec->spec; |
6928 | spec->linear_tone_beep = 0; | 3867 | spec->linear_tone_beep = 0; |
6929 | codec->patch_ops = stac92xx_patch_ops; | 3868 | spec->gen.own_eapd_ctl = 1; |
6930 | switch (codec->vendor_id) { | ||
6931 | case 0x111d76b6: | ||
6932 | case 0x111d76b7: | ||
6933 | break; | ||
6934 | case 0x111d7603: | ||
6935 | case 0x111d7608: | ||
6936 | /* On 92HD75Bx 0x27 isn't a pin nid */ | ||
6937 | spec->num_pins--; | ||
6938 | /* fallthrough */ | ||
6939 | default: | ||
6940 | spec->pin_nids = stac92hd71bxx_pin_nids_6port; | ||
6941 | } | ||
6942 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | ||
6943 | 3869 | ||
6944 | snd_hda_pick_fixup(codec, stac92hd71bxx_models, stac92hd71bxx_fixup_tbl, | 3870 | codec->patch_ops = stac_patch_ops; |
6945 | stac92hd71bxx_fixups); | ||
6946 | 3871 | ||
6947 | /* GPIO0 = EAPD */ | 3872 | /* GPIO0 = EAPD */ |
6948 | spec->gpio_mask = 0x01; | 3873 | spec->gpio_mask = 0x01; |
6949 | spec->gpio_dir = 0x01; | 3874 | spec->gpio_dir = 0x01; |
6950 | spec->gpio_data = 0x01; | 3875 | spec->gpio_data = 0x01; |
6951 | 3876 | ||
6952 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
6953 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
6954 | |||
6955 | spec->num_caps = STAC92HD71BXX_NUM_CAPS; | ||
6956 | spec->capvols = stac92hd71bxx_capvols; | ||
6957 | spec->capsws = stac92hd71bxx_capsws; | ||
6958 | |||
6959 | switch (codec->vendor_id) { | 3877 | switch (codec->vendor_id) { |
6960 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 3878 | case 0x111d76b6: /* 4 Port without Analog Mixer */ |
6961 | case 0x111d76b7: | 3879 | case 0x111d76b7: |
6962 | unmute_init++; | 3880 | unmute_init++; |
6963 | /* fallthru */ | ||
6964 | case 0x111d76b4: /* 6 Port without Analog Mixer */ | ||
6965 | case 0x111d76b5: | ||
6966 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | ||
6967 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
6968 | stac92hd71bxx_dmic_nids, | ||
6969 | STAC92HD71BXX_NUM_DMICS); | ||
6970 | break; | 3881 | break; |
6971 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 3882 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
6972 | if ((codec->revision_id & 0xf) == 0 || | 3883 | if ((codec->revision_id & 0xf) == 0 || |
@@ -6977,21 +3888,11 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
6977 | unmute_init++; | 3888 | unmute_init++; |
6978 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 3889 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
6979 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 3890 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
6980 | spec->dmic_nids = stac92hd71bxx_dmic_5port_nids; | ||
6981 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
6982 | stac92hd71bxx_dmic_5port_nids, | ||
6983 | STAC92HD71BXX_NUM_DMICS - 1); | ||
6984 | break; | 3891 | break; |
6985 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 3892 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
6986 | if ((codec->revision_id & 0xf) == 1) | 3893 | if ((codec->revision_id & 0xf) == 1) |
6987 | spec->stream_delay = 40; /* 40 milliseconds */ | 3894 | spec->stream_delay = 40; /* 40 milliseconds */ |
6988 | 3895 | ||
6989 | /* fallthru */ | ||
6990 | default: | ||
6991 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | ||
6992 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
6993 | stac92hd71bxx_dmic_nids, | ||
6994 | STAC92HD71BXX_NUM_DMICS); | ||
6995 | break; | 3896 | break; |
6996 | } | 3897 | } |
6997 | 3898 | ||
@@ -7001,32 +3902,24 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
7001 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) | 3902 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) |
7002 | snd_hda_sequence_write_cache(codec, unmute_init); | 3903 | snd_hda_sequence_write_cache(codec, unmute_init); |
7003 | 3904 | ||
7004 | spec->aloopback_ctl = stac92hd71bxx_loopback; | 3905 | spec->aloopback_ctl = &stac92hd71bxx_loopback; |
7005 | spec->aloopback_mask = 0x50; | 3906 | spec->aloopback_mask = 0x50; |
7006 | spec->aloopback_shift = 0; | 3907 | spec->aloopback_shift = 0; |
7007 | 3908 | ||
7008 | spec->powerdown_adcs = 1; | 3909 | spec->powerdown_adcs = 1; |
7009 | spec->digbeep_nid = 0x26; | 3910 | spec->digbeep_nid = 0x26; |
7010 | spec->mux_nids = stac92hd71bxx_mux_nids; | 3911 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
7011 | spec->adc_nids = stac92hd71bxx_adc_nids; | ||
7012 | spec->smux_nids = stac92hd71bxx_smux_nids; | ||
7013 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 3912 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
7014 | 3913 | ||
7015 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | 3914 | snd_hda_pick_fixup(codec, stac92hd71bxx_models, stac92hd71bxx_fixup_tbl, |
7016 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | 3915 | stac92hd71bxx_fixups); |
7017 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
7018 | spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); | ||
7019 | |||
7020 | spec->multiout.dac_nids = spec->dac_nids; | ||
7021 | spec->default_polarity = 1; | ||
7022 | |||
7023 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3916 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
7024 | 3917 | ||
7025 | stac_setup_gpio(codec); | 3918 | stac_setup_gpio(codec); |
7026 | 3919 | ||
7027 | err = stac92xx_parse_auto_config(codec); | 3920 | err = stac_parse_auto_config(codec); |
7028 | if (err < 0) { | 3921 | if (err < 0) { |
7029 | stac92xx_free(codec); | 3922 | stac_free(codec); |
7030 | return err; | 3923 | return err; |
7031 | } | 3924 | } |
7032 | 3925 | ||
@@ -7042,42 +3935,18 @@ static int patch_stac922x(struct hda_codec *codec) | |||
7042 | struct sigmatel_spec *spec; | 3935 | struct sigmatel_spec *spec; |
7043 | int err; | 3936 | int err; |
7044 | 3937 | ||
7045 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids), | 3938 | err = alloc_stac_spec(codec); |
7046 | stac922x_pin_nids); | ||
7047 | if (err < 0) | 3939 | if (err < 0) |
7048 | return err; | 3940 | return err; |
7049 | 3941 | ||
7050 | spec = codec->spec; | 3942 | spec = codec->spec; |
7051 | spec->linear_tone_beep = 1; | 3943 | spec->linear_tone_beep = 1; |
3944 | spec->gen.own_eapd_ctl = 1; | ||
7052 | 3945 | ||
7053 | snd_hda_pick_fixup(codec, stac922x_models, stac922x_fixup_tbl, | 3946 | codec->patch_ops = stac_patch_ops; |
7054 | stac922x_fixups); | ||
7055 | |||
7056 | spec->adc_nids = stac922x_adc_nids; | ||
7057 | spec->mux_nids = stac922x_mux_nids; | ||
7058 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); | ||
7059 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); | ||
7060 | spec->num_dmics = 0; | ||
7061 | spec->num_pwrs = 0; | ||
7062 | 3947 | ||
7063 | spec->num_caps = STAC922X_NUM_CAPS; | ||
7064 | spec->capvols = stac922x_capvols; | ||
7065 | spec->capsws = stac922x_capsws; | ||
7066 | |||
7067 | spec->multiout.dac_nids = spec->dac_nids; | ||
7068 | |||
7069 | snd_hda_add_verbs(codec, stac922x_core_init); | 3948 | snd_hda_add_verbs(codec, stac922x_core_init); |
7070 | 3949 | ||
7071 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | ||
7072 | |||
7073 | err = stac92xx_parse_auto_config(codec); | ||
7074 | if (err < 0) { | ||
7075 | stac92xx_free(codec); | ||
7076 | return err; | ||
7077 | } | ||
7078 | |||
7079 | codec->patch_ops = stac92xx_patch_ops; | ||
7080 | |||
7081 | /* Fix Mux capture level; max to 2 */ | 3950 | /* Fix Mux capture level; max to 2 */ |
7082 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, | 3951 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, |
7083 | (0 << AC_AMPCAP_OFFSET_SHIFT) | | 3952 | (0 << AC_AMPCAP_OFFSET_SHIFT) | |
@@ -7085,6 +3954,16 @@ static int patch_stac922x(struct hda_codec *codec) | |||
7085 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 3954 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
7086 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 3955 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
7087 | 3956 | ||
3957 | snd_hda_pick_fixup(codec, stac922x_models, stac922x_fixup_tbl, | ||
3958 | stac922x_fixups); | ||
3959 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | ||
3960 | |||
3961 | err = stac_parse_auto_config(codec); | ||
3962 | if (err < 0) { | ||
3963 | stac_free(codec); | ||
3964 | return err; | ||
3965 | } | ||
3966 | |||
7088 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 3967 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
7089 | 3968 | ||
7090 | return 0; | 3969 | return 0; |
@@ -7095,58 +3974,40 @@ static int patch_stac927x(struct hda_codec *codec) | |||
7095 | struct sigmatel_spec *spec; | 3974 | struct sigmatel_spec *spec; |
7096 | int err; | 3975 | int err; |
7097 | 3976 | ||
7098 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids), | 3977 | err = alloc_stac_spec(codec); |
7099 | stac927x_pin_nids); | ||
7100 | if (err < 0) | 3978 | if (err < 0) |
7101 | return err; | 3979 | return err; |
7102 | 3980 | ||
7103 | spec = codec->spec; | 3981 | spec = codec->spec; |
7104 | spec->linear_tone_beep = 1; | 3982 | spec->linear_tone_beep = 1; |
7105 | codec->slave_dig_outs = stac927x_slave_dig_outs; | 3983 | spec->gen.own_eapd_ctl = 1; |
7106 | |||
7107 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, | ||
7108 | stac927x_fixups); | ||
7109 | 3984 | ||
7110 | spec->digbeep_nid = 0x23; | 3985 | spec->digbeep_nid = 0x23; |
7111 | spec->adc_nids = stac927x_adc_nids; | ||
7112 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
7113 | spec->mux_nids = stac927x_mux_nids; | ||
7114 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | ||
7115 | spec->smux_nids = stac927x_smux_nids; | ||
7116 | spec->num_smuxes = ARRAY_SIZE(stac927x_smux_nids); | ||
7117 | spec->spdif_labels = stac927x_spdif_labels; | ||
7118 | spec->dac_list = stac927x_dac_nids; | ||
7119 | spec->multiout.dac_nids = spec->dac_nids; | ||
7120 | 3986 | ||
7121 | /* GPIO0 High = Enable EAPD */ | 3987 | /* GPIO0 High = Enable EAPD */ |
7122 | spec->eapd_mask = spec->gpio_mask = 0x01; | 3988 | spec->eapd_mask = spec->gpio_mask = 0x01; |
7123 | spec->gpio_dir = spec->gpio_data = 0x01; | 3989 | spec->gpio_dir = spec->gpio_data = 0x01; |
7124 | 3990 | ||
7125 | spec->num_dmics = 0; | 3991 | spec->aloopback_ctl = &stac927x_loopback; |
7126 | |||
7127 | spec->num_caps = STAC927X_NUM_CAPS; | ||
7128 | spec->capvols = stac927x_capvols; | ||
7129 | spec->capsws = stac927x_capsws; | ||
7130 | |||
7131 | spec->num_pwrs = 0; | ||
7132 | spec->aloopback_ctl = stac927x_loopback; | ||
7133 | spec->aloopback_mask = 0x40; | 3992 | spec->aloopback_mask = 0x40; |
7134 | spec->aloopback_shift = 0; | 3993 | spec->aloopback_shift = 0; |
7135 | spec->eapd_switch = 1; | 3994 | spec->eapd_switch = 1; |
7136 | 3995 | ||
3996 | codec->patch_ops = stac_patch_ops; | ||
3997 | |||
3998 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, | ||
3999 | stac927x_fixups); | ||
7137 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4000 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
7138 | 4001 | ||
7139 | if (!spec->volknob_init) | 4002 | if (!spec->volknob_init) |
7140 | snd_hda_add_verbs(codec, stac927x_core_init); | 4003 | snd_hda_add_verbs(codec, stac927x_core_init); |
7141 | 4004 | ||
7142 | err = stac92xx_parse_auto_config(codec); | 4005 | err = stac_parse_auto_config(codec); |
7143 | if (err < 0) { | 4006 | if (err < 0) { |
7144 | stac92xx_free(codec); | 4007 | stac_free(codec); |
7145 | return err; | 4008 | return err; |
7146 | } | 4009 | } |
7147 | 4010 | ||
7148 | codec->patch_ops = stac92xx_patch_ops; | ||
7149 | |||
7150 | codec->proc_widget_hook = stac927x_proc_hook; | 4011 | codec->proc_widget_hook = stac927x_proc_hook; |
7151 | 4012 | ||
7152 | /* | 4013 | /* |
@@ -7171,40 +4032,21 @@ static int patch_stac9205(struct hda_codec *codec) | |||
7171 | struct sigmatel_spec *spec; | 4032 | struct sigmatel_spec *spec; |
7172 | int err; | 4033 | int err; |
7173 | 4034 | ||
7174 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids), | 4035 | err = alloc_stac_spec(codec); |
7175 | stac9205_pin_nids); | ||
7176 | if (err < 0) | 4036 | if (err < 0) |
7177 | return err; | 4037 | return err; |
7178 | 4038 | ||
7179 | spec = codec->spec; | 4039 | spec = codec->spec; |
7180 | spec->linear_tone_beep = 1; | 4040 | spec->linear_tone_beep = 1; |
7181 | 4041 | spec->gen.own_eapd_ctl = 1; | |
7182 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, | ||
7183 | stac9205_fixups); | ||
7184 | 4042 | ||
7185 | spec->digbeep_nid = 0x23; | 4043 | spec->digbeep_nid = 0x23; |
7186 | spec->adc_nids = stac9205_adc_nids; | ||
7187 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); | ||
7188 | spec->mux_nids = stac9205_mux_nids; | ||
7189 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | ||
7190 | spec->smux_nids = stac9205_smux_nids; | ||
7191 | spec->num_smuxes = ARRAY_SIZE(stac9205_smux_nids); | ||
7192 | spec->dmic_nids = stac9205_dmic_nids; | ||
7193 | spec->num_dmics = STAC9205_NUM_DMICS; | ||
7194 | spec->dmux_nids = stac9205_dmux_nids; | ||
7195 | spec->num_dmuxes = ARRAY_SIZE(stac9205_dmux_nids); | ||
7196 | spec->num_pwrs = 0; | ||
7197 | 4044 | ||
7198 | snd_hda_add_verbs(codec, stac9205_core_init); | 4045 | snd_hda_add_verbs(codec, stac9205_core_init); |
7199 | spec->aloopback_ctl = stac9205_loopback; | 4046 | spec->aloopback_ctl = &stac9205_loopback; |
7200 | |||
7201 | spec->num_caps = STAC9205_NUM_CAPS; | ||
7202 | spec->capvols = stac9205_capvols; | ||
7203 | spec->capsws = stac9205_capsws; | ||
7204 | 4047 | ||
7205 | spec->aloopback_mask = 0x40; | 4048 | spec->aloopback_mask = 0x40; |
7206 | spec->aloopback_shift = 0; | 4049 | spec->aloopback_shift = 0; |
7207 | spec->multiout.dac_nids = spec->dac_nids; | ||
7208 | 4050 | ||
7209 | /* GPIO0 High = EAPD */ | 4051 | /* GPIO0 High = EAPD */ |
7210 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 4052 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
@@ -7213,16 +4055,18 @@ static int patch_stac9205(struct hda_codec *codec) | |||
7213 | /* Turn on/off EAPD per HP plugging */ | 4055 | /* Turn on/off EAPD per HP plugging */ |
7214 | spec->eapd_switch = 1; | 4056 | spec->eapd_switch = 1; |
7215 | 4057 | ||
4058 | codec->patch_ops = stac_patch_ops; | ||
4059 | |||
4060 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, | ||
4061 | stac9205_fixups); | ||
7216 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4062 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
7217 | 4063 | ||
7218 | err = stac92xx_parse_auto_config(codec); | 4064 | err = stac_parse_auto_config(codec); |
7219 | if (err < 0) { | 4065 | if (err < 0) { |
7220 | stac92xx_free(codec); | 4066 | stac_free(codec); |
7221 | return err; | 4067 | return err; |
7222 | } | 4068 | } |
7223 | 4069 | ||
7224 | codec->patch_ops = stac92xx_patch_ops; | ||
7225 | |||
7226 | codec->proc_widget_hook = stac9205_proc_hook; | 4070 | codec->proc_widget_hook = stac9205_proc_hook; |
7227 | 4071 | ||
7228 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4072 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
@@ -7240,24 +4084,6 @@ static const struct hda_verb stac9872_core_init[] = { | |||
7240 | {} | 4084 | {} |
7241 | }; | 4085 | }; |
7242 | 4086 | ||
7243 | static const hda_nid_t stac9872_pin_nids[] = { | ||
7244 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
7245 | 0x11, 0x13, 0x14, | ||
7246 | }; | ||
7247 | |||
7248 | static const hda_nid_t stac9872_adc_nids[] = { | ||
7249 | 0x8 /*,0x6*/ | ||
7250 | }; | ||
7251 | |||
7252 | static const hda_nid_t stac9872_mux_nids[] = { | ||
7253 | 0x15 | ||
7254 | }; | ||
7255 | |||
7256 | static const unsigned long stac9872_capvols[] = { | ||
7257 | HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), | ||
7258 | }; | ||
7259 | #define stac9872_capsws stac9872_capvols | ||
7260 | |||
7261 | static const struct hda_pintbl stac9872_vaio_pin_configs[] = { | 4087 | static const struct hda_pintbl stac9872_vaio_pin_configs[] = { |
7262 | { 0x0a, 0x03211020 }, | 4088 | { 0x0a, 0x03211020 }, |
7263 | { 0x0b, 0x411111f0 }, | 4089 | { 0x0b, 0x411111f0 }, |
@@ -7294,36 +4120,27 @@ static int patch_stac9872(struct hda_codec *codec) | |||
7294 | struct sigmatel_spec *spec; | 4120 | struct sigmatel_spec *spec; |
7295 | int err; | 4121 | int err; |
7296 | 4122 | ||
7297 | err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids), | 4123 | err = alloc_stac_spec(codec); |
7298 | stac9872_pin_nids); | ||
7299 | if (err < 0) | 4124 | if (err < 0) |
7300 | return err; | 4125 | return err; |
7301 | 4126 | ||
7302 | spec = codec->spec; | 4127 | spec = codec->spec; |
7303 | spec->linear_tone_beep = 1; | 4128 | spec->linear_tone_beep = 1; |
4129 | spec->gen.own_eapd_ctl = 1; | ||
7304 | 4130 | ||
7305 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, | 4131 | codec->patch_ops = stac_patch_ops; |
7306 | stac9872_fixups); | ||
7307 | 4132 | ||
7308 | spec->multiout.dac_nids = spec->dac_nids; | ||
7309 | spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); | ||
7310 | spec->adc_nids = stac9872_adc_nids; | ||
7311 | spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); | ||
7312 | spec->mux_nids = stac9872_mux_nids; | ||
7313 | spec->num_caps = 1; | ||
7314 | spec->capvols = stac9872_capvols; | ||
7315 | spec->capsws = stac9872_capsws; | ||
7316 | snd_hda_add_verbs(codec, stac9872_core_init); | 4133 | snd_hda_add_verbs(codec, stac9872_core_init); |
7317 | 4134 | ||
4135 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, | ||
4136 | stac9872_fixups); | ||
7318 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4137 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
7319 | 4138 | ||
7320 | err = stac92xx_parse_auto_config(codec); | 4139 | err = stac_parse_auto_config(codec); |
7321 | if (err < 0) { | 4140 | if (err < 0) { |
7322 | stac92xx_free(codec); | 4141 | stac_free(codec); |
7323 | return -EINVAL; | 4142 | return -EINVAL; |
7324 | } | 4143 | } |
7325 | spec->input_mux = &spec->private_imux; | ||
7326 | codec->patch_ops = stac92xx_patch_ops; | ||
7327 | 4144 | ||
7328 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4145 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
7329 | 4146 | ||