summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorLydia Wang <lydiawang@viatech.com.cn>2011-07-08 02:02:52 -0400
committerTakashi Iwai <tiwai@suse.de>2011-07-08 02:18:29 -0400
commitd69607b3c39bb46b7f838f7b683716d4c22ee353 (patch)
treeee6858739ed3fda6fe857ac6562335930f902cbf /sound
parent1d045db96ad9b8f4d876d5945ab097425252e4ab (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.c104
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
441static 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 */
454static 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 */
442static void activate_output_path(struct hda_codec *codec, struct nid_path *path, 491static 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
547static void via_auto_init_multi_out(struct hda_codec *codec) 577static void via_auto_init_multi_out(struct hda_codec *codec)