diff options
author | Lydia Wang <lydiawang@viatech.com.cn> | 2011-07-08 02:02:52 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-07-08 02:18:29 -0400 |
commit | d69607b3c39bb46b7f838f7b683716d4c22ee353 (patch) | |
tree | ee6858739ed3fda6fe857ac6562335930f902cbf /sound | |
parent | 1d045db96ad9b8f4d876d5945ab097425252e4ab (diff) |
ALSA: hda - Fix VIA output-path init for VT2002P/1802/1812
For VT2002P, VT1802 and VT1812 codecs, the original activate_output_path()
function can't initialize output and hp path correctly, since mixers connected to
output pin widgets are not considered. So modify the activate_output_path()
function to satisify this kind of codec.
Signed-off-by: Lydia Wang <lydiawang@viatech.com.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_via.c | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 42d5a91781fc..8f59e0b5d477 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -438,11 +438,62 @@ static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
438 | #define have_mute(codec, nid, dir) \ | 438 | #define have_mute(codec, nid, dir) \ |
439 | check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) | 439 | check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) |
440 | 440 | ||
441 | static bool is_node_in_path(struct nid_path *path, hda_nid_t nid) | ||
442 | { | ||
443 | int i; | ||
444 | if (!nid) | ||
445 | return false; | ||
446 | for (i = 0; i < path->depth; i++) { | ||
447 | if (path->path[i] == nid) | ||
448 | return true; | ||
449 | } | ||
450 | return false; | ||
451 | } | ||
452 | |||
453 | /* enable/disable the output-route mixers */ | ||
454 | static void activate_output_mix(struct hda_codec *codec, struct nid_path *path, | ||
455 | hda_nid_t mix_nid, int aa_mix_idx, bool enable) | ||
456 | { | ||
457 | int i, num, val; | ||
458 | bool hp_path, front_path; | ||
459 | struct via_spec *spec = codec->spec; | ||
460 | |||
461 | if (!path) | ||
462 | return; | ||
463 | num = snd_hda_get_conn_list(codec, mix_nid, NULL); | ||
464 | hp_path = is_node_in_path(path, spec->hp_dac_nid); | ||
465 | front_path = is_node_in_path(path, spec->multiout.dac_nids[0]); | ||
466 | |||
467 | for (i = 0; i < num; i++) { | ||
468 | if (i == aa_mix_idx) { | ||
469 | if (hp_path) | ||
470 | val = enable ? AMP_IN_MUTE(i) : | ||
471 | AMP_IN_UNMUTE(i); | ||
472 | else if (front_path) | ||
473 | val = AMP_IN_UNMUTE(i); | ||
474 | else | ||
475 | val = AMP_IN_MUTE(i); | ||
476 | } else { | ||
477 | if (hp_path) | ||
478 | val = enable ? AMP_IN_UNMUTE(i) : | ||
479 | AMP_IN_MUTE(i); | ||
480 | else if (front_path) | ||
481 | val = AMP_IN_MUTE(i); | ||
482 | else | ||
483 | val = AMP_IN_UNMUTE(i); | ||
484 | } | ||
485 | snd_hda_codec_write(codec, mix_nid, 0, | ||
486 | AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
487 | } | ||
488 | } | ||
489 | |||
441 | /* enable/disable the output-route */ | 490 | /* enable/disable the output-route */ |
442 | static void activate_output_path(struct hda_codec *codec, struct nid_path *path, | 491 | static void activate_output_path(struct hda_codec *codec, struct nid_path *path, |
443 | bool enable, bool force) | 492 | bool enable, bool force) |
444 | { | 493 | { |
445 | int i; | 494 | int i, val; |
495 | struct via_spec *spec = codec->spec; | ||
496 | hda_nid_t aa_mix_nid = spec->aa_mix_nid; | ||
446 | for (i = 0; i < path->depth; i++) { | 497 | for (i = 0; i < path->depth; i++) { |
447 | hda_nid_t src, dst; | 498 | hda_nid_t src, dst; |
448 | int idx = path->idx[i]; | 499 | int idx = path->idx[i]; |
@@ -459,10 +510,19 @@ static void activate_output_path(struct hda_codec *codec, struct nid_path *path, | |||
459 | && get_wcaps_type(get_wcaps(codec, dst)) == AC_WID_AUD_MIX) | 510 | && get_wcaps_type(get_wcaps(codec, dst)) == AC_WID_AUD_MIX) |
460 | continue; | 511 | continue; |
461 | if (have_mute(codec, dst, HDA_INPUT)) { | 512 | if (have_mute(codec, dst, HDA_INPUT)) { |
462 | int val = enable ? AMP_IN_UNMUTE(idx) : | 513 | if (dst == aa_mix_nid) { |
463 | AMP_IN_MUTE(idx); | 514 | val = enable ? AMP_IN_UNMUTE(idx) : |
464 | snd_hda_codec_write(codec, dst, 0, | 515 | AMP_IN_MUTE(idx); |
465 | AC_VERB_SET_AMP_GAIN_MUTE, val); | 516 | snd_hda_codec_write(codec, dst, 0, |
517 | AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
518 | } else { | ||
519 | idx = get_connection_index(codec, dst, | ||
520 | aa_mix_nid); | ||
521 | if (idx >= 0) { | ||
522 | activate_output_mix(codec, path, | ||
523 | dst, idx, enable); | ||
524 | } | ||
525 | } | ||
466 | } | 526 | } |
467 | if (!force && (src == path->vol_ctl || src == path->mute_ctl)) | 527 | if (!force && (src == path->vol_ctl || src == path->mute_ctl)) |
468 | continue; | 528 | continue; |
@@ -493,8 +553,7 @@ static void via_auto_init_output(struct hda_codec *codec, | |||
493 | { | 553 | { |
494 | struct via_spec *spec = codec->spec; | 554 | struct via_spec *spec = codec->spec; |
495 | unsigned int caps; | 555 | unsigned int caps; |
496 | hda_nid_t pin, nid, pre_nid; | 556 | hda_nid_t pin; |
497 | int i, idx, j, num; | ||
498 | 557 | ||
499 | if (!path->depth) | 558 | if (!path->depth) |
500 | return; | 559 | return; |
@@ -509,39 +568,10 @@ static void via_auto_init_output(struct hda_codec *codec, | |||
509 | AMP_OUT_MUTE | val); | 568 | AMP_OUT_MUTE | val); |
510 | } | 569 | } |
511 | 570 | ||
512 | activate_output_path(codec, path, true, force); | ||
513 | |||
514 | /* initialize the AA-path */ | 571 | /* initialize the AA-path */ |
515 | if (!spec->aa_mix_nid) | 572 | if (!spec->aa_mix_nid) |
516 | return; | 573 | return; |
517 | for (i = path->depth - 1; i > 0; i--) { | 574 | activate_output_path(codec, path, true, force); |
518 | nid = path->path[i]; | ||
519 | pre_nid = path->path[i - 1]; | ||
520 | idx = get_connection_index(codec, nid, spec->aa_mix_nid); | ||
521 | if (idx >= 0) { | ||
522 | if (have_mute(codec, nid, HDA_INPUT)) { | ||
523 | unsigned int mute = with_aa_mix ? | ||
524 | AMP_IN_UNMUTE(idx) : AMP_IN_MUTE(idx); | ||
525 | snd_hda_codec_write(codec, nid, 0, | ||
526 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
527 | mute); | ||
528 | /* exclusively via aa-mix for front */ | ||
529 | if (pre_nid == spec->multiout.dac_nids[0]) { | ||
530 | num = snd_hda_get_conn_list(codec, nid, | ||
531 | NULL); | ||
532 | for (j = 0; j < num; j++) { | ||
533 | if (j == idx) | ||
534 | continue; | ||
535 | snd_hda_codec_write(codec, | ||
536 | nid, 0, | ||
537 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
538 | AMP_IN_MUTE(j)); | ||
539 | } | ||
540 | } | ||
541 | } | ||
542 | break; | ||
543 | } | ||
544 | } | ||
545 | } | 575 | } |
546 | 576 | ||
547 | static void via_auto_init_multi_out(struct hda_codec *codec) | 577 | static void via_auto_init_multi_out(struct hda_codec *codec) |