diff options
author | Josepch Chan <josephchan@via.com.tw> | 2007-12-13 10:40:40 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:33 -0500 |
commit | f7278fd0a57ea6cde4988ab820851b01be20daef (patch) | |
tree | 34ce3a3a42393353f69e26260466192887a5f4c5 /sound/pci/hda | |
parent | 64e0e2d987f5e803f001c853a433ef2fc51640cb (diff) |
[ALSA] hda-codec - Add support for VIA VT1708B HD audio codec
This patch adds support for VIA new HD audio codec, VT1708B.
Signed-off-by: Josepch Chan <josephchan@via.com.tw>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_via.c | 675 |
1 files changed, 625 insertions, 50 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4cdf3e6df4ba..d42d8f753f11 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -27,6 +27,8 @@ | |||
27 | /* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */ | 27 | /* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */ |
28 | /* 2006-08-02 Lydia Wang Add support to VT1709 codec */ | 28 | /* 2006-08-02 Lydia Wang Add support to VT1709 codec */ |
29 | /* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */ | 29 | /* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */ |
30 | /* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */ | ||
31 | /* 2007-09-17 Lydia Wang Add VT1708B codec support */ | ||
30 | /* */ | 32 | /* */ |
31 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 33 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
32 | 34 | ||
@@ -51,14 +53,23 @@ | |||
51 | #define VT1708_HP_NID 0x13 | 53 | #define VT1708_HP_NID 0x13 |
52 | #define VT1708_DIGOUT_NID 0x14 | 54 | #define VT1708_DIGOUT_NID 0x14 |
53 | #define VT1708_DIGIN_NID 0x16 | 55 | #define VT1708_DIGIN_NID 0x16 |
56 | #define VT1708_DIGIN_PIN 0x26 | ||
54 | 57 | ||
55 | #define VT1709_HP_DAC_NID 0x28 | 58 | #define VT1709_HP_DAC_NID 0x28 |
56 | #define VT1709_DIGOUT_NID 0x13 | 59 | #define VT1709_DIGOUT_NID 0x13 |
57 | #define VT1709_DIGIN_NID 0x17 | 60 | #define VT1709_DIGIN_NID 0x17 |
61 | #define VT1709_DIGIN_PIN 0x25 | ||
62 | |||
63 | #define VT1708B_HP_NID 0x25 | ||
64 | #define VT1708B_DIGOUT_NID 0x12 | ||
65 | #define VT1708B_DIGIN_NID 0x15 | ||
66 | #define VT1708B_DIGIN_PIN 0x21 | ||
58 | 67 | ||
59 | #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b) | 68 | #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b) |
60 | #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713) | 69 | #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713) |
61 | #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717) | 70 | #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717) |
71 | #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723) | ||
72 | #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727) | ||
62 | 73 | ||
63 | 74 | ||
64 | enum { | 75 | enum { |
@@ -131,6 +142,11 @@ static hda_nid_t vt1709_adc_nids[3] = { | |||
131 | 0x14, 0x15, 0x16 | 142 | 0x14, 0x15, 0x16 |
132 | }; | 143 | }; |
133 | 144 | ||
145 | static hda_nid_t vt1708B_adc_nids[2] = { | ||
146 | /* ADC1-2 */ | ||
147 | 0x13, 0x14 | ||
148 | }; | ||
149 | |||
134 | /* add dynamic controls */ | 150 | /* add dynamic controls */ |
135 | static int via_add_control(struct via_spec *spec, int type, const char *name, | 151 | static int via_add_control(struct via_spec *spec, int type, const char *name, |
136 | unsigned long val) | 152 | unsigned long val) |
@@ -268,9 +284,13 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
268 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 284 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, |
269 | 0x18, &spec->cur_mux[adc_idx]); | 285 | 0x18, &spec->cur_mux[adc_idx]); |
270 | else if ((IS_VT1709_10CH_VENDORID(vendor_id) || | 286 | else if ((IS_VT1709_10CH_VENDORID(vendor_id) || |
271 | IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) ) | 287 | IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0) |
272 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 288 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, |
273 | 0x19, &spec->cur_mux[adc_idx]); | 289 | 0x19, &spec->cur_mux[adc_idx]); |
290 | else if ((IS_VT1708B_8CH_VENDORID(vendor_id) || | ||
291 | IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0) | ||
292 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
293 | 0x17, &spec->cur_mux[adc_idx]); | ||
274 | else | 294 | else |
275 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 295 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, |
276 | spec->adc_nids[adc_idx], | 296 | spec->adc_nids[adc_idx], |
@@ -309,15 +329,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
309 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 329 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
310 | 330 | ||
311 | 331 | ||
312 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 332 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
313 | * mixer widget | 333 | * mixer widget |
314 | */ | 334 | */ |
315 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 335 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */ | 336 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
317 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 337 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
318 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 338 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
319 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 339 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
320 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 340 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
321 | 341 | ||
322 | /* | 342 | /* |
323 | * Set up output mixers (0x19 - 0x1b) | 343 | * Set up output mixers (0x19 - 0x1b) |
@@ -329,10 +349,9 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
329 | 349 | ||
330 | /* Setup default input to PW4 */ | 350 | /* Setup default input to PW4 */ |
331 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, | 351 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, |
332 | /* Set mic as default input of sw0 */ | ||
333 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
334 | /* PW9 Output enable */ | 352 | /* PW9 Output enable */ |
335 | {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 353 | {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
354 | { } | ||
336 | }; | 355 | }; |
337 | 356 | ||
338 | static int via_playback_pcm_open(struct hda_pcm_stream *hinfo, | 357 | static int via_playback_pcm_open(struct hda_pcm_stream *hinfo, |
@@ -544,6 +563,31 @@ static int via_init(struct hda_codec *codec) | |||
544 | { | 563 | { |
545 | struct via_spec *spec = codec->spec; | 564 | struct via_spec *spec = codec->spec; |
546 | snd_hda_sequence_write(codec, spec->init_verbs); | 565 | snd_hda_sequence_write(codec, spec->init_verbs); |
566 | /* Lydia Add for EAPD enable */ | ||
567 | if (!spec->dig_in_nid) { /* No Digital In connection */ | ||
568 | if (IS_VT1708_VENDORID(codec->vendor_id)) { | ||
569 | snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0, | ||
570 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
571 | 0x40); | ||
572 | snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0, | ||
573 | AC_VERB_SET_EAPD_BTLENABLE, 0x02); | ||
574 | } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) || | ||
575 | IS_VT1709_6CH_VENDORID(codec->vendor_id)) { | ||
576 | snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0, | ||
577 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
578 | 0x40); | ||
579 | snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0, | ||
580 | AC_VERB_SET_EAPD_BTLENABLE, 0x02); | ||
581 | } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) || | ||
582 | IS_VT1708B_4CH_VENDORID(codec->vendor_id)) { | ||
583 | snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0, | ||
584 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
585 | 0x40); | ||
586 | snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0, | ||
587 | AC_VERB_SET_EAPD_BTLENABLE, 0x02); | ||
588 | } | ||
589 | } | ||
590 | |||
547 | return 0; | 591 | return 0; |
548 | } | 592 | } |
549 | 593 | ||
@@ -623,58 +667,68 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec, | |||
623 | if (i == AUTO_SEQ_CENLFE) { | 667 | if (i == AUTO_SEQ_CENLFE) { |
624 | /* Center/LFE */ | 668 | /* Center/LFE */ |
625 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 669 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
626 | "Center Playback Volume", | 670 | "Center Playback Volume", |
627 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT)); | 671 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, |
672 | HDA_OUTPUT)); | ||
628 | if (err < 0) | 673 | if (err < 0) |
629 | return err; | 674 | return err; |
630 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 675 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
631 | "LFE Playback Volume", | 676 | "LFE Playback Volume", |
632 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT)); | 677 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, |
678 | HDA_OUTPUT)); | ||
633 | if (err < 0) | 679 | if (err < 0) |
634 | return err; | 680 | return err; |
635 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 681 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
636 | "Center Playback Switch", | 682 | "Center Playback Switch", |
637 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT)); | 683 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, |
684 | HDA_OUTPUT)); | ||
638 | if (err < 0) | 685 | if (err < 0) |
639 | return err; | 686 | return err; |
640 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 687 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
641 | "LFE Playback Switch", | 688 | "LFE Playback Switch", |
642 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT)); | 689 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, |
690 | HDA_OUTPUT)); | ||
643 | if (err < 0) | 691 | if (err < 0) |
644 | return err; | 692 | return err; |
645 | } else if (i == AUTO_SEQ_FRONT){ | 693 | } else if (i == AUTO_SEQ_FRONT){ |
646 | /* add control to mixer index 0 */ | 694 | /* add control to mixer index 0 */ |
647 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 695 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
648 | "Master Front Playback Volume", | 696 | "Master Front Playback Volume", |
649 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT)); | 697 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, |
698 | HDA_INPUT)); | ||
650 | if (err < 0) | 699 | if (err < 0) |
651 | return err; | 700 | return err; |
652 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 701 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
653 | "Master Front Playback Switch", | 702 | "Master Front Playback Switch", |
654 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT)); | 703 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, |
704 | HDA_INPUT)); | ||
655 | if (err < 0) | 705 | if (err < 0) |
656 | return err; | 706 | return err; |
657 | 707 | ||
658 | /* add control to PW3 */ | 708 | /* add control to PW3 */ |
659 | sprintf(name, "%s Playback Volume", chname[i]); | 709 | sprintf(name, "%s Playback Volume", chname[i]); |
660 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 710 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, |
661 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 711 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
712 | HDA_OUTPUT)); | ||
662 | if (err < 0) | 713 | if (err < 0) |
663 | return err; | 714 | return err; |
664 | sprintf(name, "%s Playback Switch", chname[i]); | 715 | sprintf(name, "%s Playback Switch", chname[i]); |
665 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | 716 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, |
666 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 717 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
718 | HDA_OUTPUT)); | ||
667 | if (err < 0) | 719 | if (err < 0) |
668 | return err; | 720 | return err; |
669 | } else { | 721 | } else { |
670 | sprintf(name, "%s Playback Volume", chname[i]); | 722 | sprintf(name, "%s Playback Volume", chname[i]); |
671 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 723 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, |
672 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT)); | 724 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, |
725 | HDA_OUTPUT)); | ||
673 | if (err < 0) | 726 | if (err < 0) |
674 | return err; | 727 | return err; |
675 | sprintf(name, "%s Playback Switch", chname[i]); | 728 | sprintf(name, "%s Playback Switch", chname[i]); |
676 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | 729 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, |
677 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT)); | 730 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, |
731 | HDA_OUTPUT)); | ||
678 | if (err < 0) | 732 | if (err < 0) |
679 | return err; | 733 | return err; |
680 | } | 734 | } |
@@ -899,15 +953,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
899 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 953 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
900 | 954 | ||
901 | 955 | ||
902 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 956 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
903 | * mixer widget | 957 | * mixer widget |
904 | */ | 958 | */ |
905 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 959 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */ | 960 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
907 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 961 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
908 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 962 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
909 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 963 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
910 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 964 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
911 | 965 | ||
912 | /* | 966 | /* |
913 | * Set up output selector (0x1a, 0x1b, 0x29) | 967 | * Set up output selector (0x1a, 0x1b, 0x29) |
@@ -925,8 +979,6 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
925 | 979 | ||
926 | /* Set input of PW4 as AOW4 */ | 980 | /* Set input of PW4 as AOW4 */ |
927 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, | 981 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x1}, |
928 | /* Set mic as default input of sw0 */ | ||
929 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
930 | /* PW9 Output enable */ | 982 | /* PW9 Output enable */ |
931 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 983 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
932 | { } | 984 | { } |
@@ -1073,68 +1125,80 @@ static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec, | |||
1073 | /* Center/LFE */ | 1125 | /* Center/LFE */ |
1074 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 1126 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
1075 | "Center Playback Volume", | 1127 | "Center Playback Volume", |
1076 | HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT)); | 1128 | HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, |
1129 | HDA_OUTPUT)); | ||
1077 | if (err < 0) | 1130 | if (err < 0) |
1078 | return err; | 1131 | return err; |
1079 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 1132 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
1080 | "LFE Playback Volume", | 1133 | "LFE Playback Volume", |
1081 | HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT)); | 1134 | HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, |
1135 | HDA_OUTPUT)); | ||
1082 | if (err < 0) | 1136 | if (err < 0) |
1083 | return err; | 1137 | return err; |
1084 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 1138 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
1085 | "Center Playback Switch", | 1139 | "Center Playback Switch", |
1086 | HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT)); | 1140 | HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, |
1141 | HDA_OUTPUT)); | ||
1087 | if (err < 0) | 1142 | if (err < 0) |
1088 | return err; | 1143 | return err; |
1089 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 1144 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
1090 | "LFE Playback Switch", | 1145 | "LFE Playback Switch", |
1091 | HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT)); | 1146 | HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, |
1147 | HDA_OUTPUT)); | ||
1092 | if (err < 0) | 1148 | if (err < 0) |
1093 | return err; | 1149 | return err; |
1094 | } else if (i == AUTO_SEQ_FRONT){ | 1150 | } else if (i == AUTO_SEQ_FRONT){ |
1095 | /* add control to mixer index 0 */ | 1151 | /* add control to mixer index 0 */ |
1096 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 1152 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
1097 | "Master Front Playback Volume", | 1153 | "Master Front Playback Volume", |
1098 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT)); | 1154 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, |
1155 | HDA_INPUT)); | ||
1099 | if (err < 0) | 1156 | if (err < 0) |
1100 | return err; | 1157 | return err; |
1101 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | 1158 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, |
1102 | "Master Front Playback Switch", | 1159 | "Master Front Playback Switch", |
1103 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT)); | 1160 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, |
1161 | HDA_INPUT)); | ||
1104 | if (err < 0) | 1162 | if (err < 0) |
1105 | return err; | 1163 | return err; |
1106 | 1164 | ||
1107 | /* add control to PW3 */ | 1165 | /* add control to PW3 */ |
1108 | sprintf(name, "%s Playback Volume", chname[i]); | 1166 | sprintf(name, "%s Playback Volume", chname[i]); |
1109 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 1167 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, |
1110 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 1168 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
1169 | HDA_OUTPUT)); | ||
1111 | if (err < 0) | 1170 | if (err < 0) |
1112 | return err; | 1171 | return err; |
1113 | sprintf(name, "%s Playback Switch", chname[i]); | 1172 | sprintf(name, "%s Playback Switch", chname[i]); |
1114 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | 1173 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, |
1115 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 1174 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
1175 | HDA_OUTPUT)); | ||
1116 | if (err < 0) | 1176 | if (err < 0) |
1117 | return err; | 1177 | return err; |
1118 | } else if (i == AUTO_SEQ_SURROUND) { | 1178 | } else if (i == AUTO_SEQ_SURROUND) { |
1119 | sprintf(name, "%s Playback Volume", chname[i]); | 1179 | sprintf(name, "%s Playback Volume", chname[i]); |
1120 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 1180 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, |
1121 | HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT)); | 1181 | HDA_COMPOSE_AMP_VAL(0x29, 3, 0, |
1182 | HDA_OUTPUT)); | ||
1122 | if (err < 0) | 1183 | if (err < 0) |
1123 | return err; | 1184 | return err; |
1124 | sprintf(name, "%s Playback Switch", chname[i]); | 1185 | sprintf(name, "%s Playback Switch", chname[i]); |
1125 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | 1186 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, |
1126 | HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT)); | 1187 | HDA_COMPOSE_AMP_VAL(0x29, 3, 0, |
1188 | HDA_OUTPUT)); | ||
1127 | if (err < 0) | 1189 | if (err < 0) |
1128 | return err; | 1190 | return err; |
1129 | } else if (i == AUTO_SEQ_SIDE) { | 1191 | } else if (i == AUTO_SEQ_SIDE) { |
1130 | sprintf(name, "%s Playback Volume", chname[i]); | 1192 | sprintf(name, "%s Playback Volume", chname[i]); |
1131 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 1193 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, |
1132 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT)); | 1194 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, |
1195 | HDA_OUTPUT)); | ||
1133 | if (err < 0) | 1196 | if (err < 0) |
1134 | return err; | 1197 | return err; |
1135 | sprintf(name, "%s Playback Switch", chname[i]); | 1198 | sprintf(name, "%s Playback Switch", chname[i]); |
1136 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | 1199 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, |
1137 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT)); | 1200 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, |
1201 | HDA_OUTPUT)); | ||
1138 | if (err < 0) | 1202 | if (err < 0) |
1139 | return err; | 1203 | return err; |
1140 | } | 1204 | } |
@@ -1351,8 +1415,6 @@ static struct hda_verb vt1709_6ch_volume_init_verbs[] = { | |||
1351 | 1415 | ||
1352 | /* Set input of PW4 as MW0 */ | 1416 | /* Set input of PW4 as MW0 */ |
1353 | {0x20, AC_VERB_SET_CONNECT_SEL, 0}, | 1417 | {0x20, AC_VERB_SET_CONNECT_SEL, 0}, |
1354 | /* Set mic as default input of sw0 */ | ||
1355 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
1356 | /* PW9 Output enable */ | 1418 | /* PW9 Output enable */ |
1357 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 1419 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
1358 | { } | 1420 | { } |
@@ -1403,6 +1465,495 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
1403 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1465 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1404 | spec->loopback.amplist = vt1709_loopbacks; | 1466 | spec->loopback.amplist = vt1709_loopbacks; |
1405 | #endif | 1467 | #endif |
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | /* capture mixer elements */ | ||
1472 | static struct snd_kcontrol_new vt1708B_capture_mixer[] = { | ||
1473 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), | ||
1474 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), | ||
1475 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), | ||
1476 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT), | ||
1477 | { | ||
1478 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1479 | /* The multiple "Capture Source" controls confuse alsamixer | ||
1480 | * So call somewhat different.. | ||
1481 | * FIXME: the controls appear in the "playback" view! | ||
1482 | */ | ||
1483 | /* .name = "Capture Source", */ | ||
1484 | .name = "Input Source", | ||
1485 | .count = 1, | ||
1486 | .info = via_mux_enum_info, | ||
1487 | .get = via_mux_enum_get, | ||
1488 | .put = via_mux_enum_put, | ||
1489 | }, | ||
1490 | { } /* end */ | ||
1491 | }; | ||
1492 | /* | ||
1493 | * generic initialization of ADC, input mixers and output mixers | ||
1494 | */ | ||
1495 | static struct hda_verb vt1708B_8ch_volume_init_verbs[] = { | ||
1496 | /* | ||
1497 | * Unmute ADC0-1 and set the default input to mic-in | ||
1498 | */ | ||
1499 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1500 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1501 | |||
1502 | |||
1503 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
1504 | * mixer widget | ||
1505 | */ | ||
1506 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | ||
1507 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1508 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1509 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
1510 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
1511 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
1512 | |||
1513 | /* | ||
1514 | * Set up output mixers | ||
1515 | */ | ||
1516 | /* set vol=0 to output mixers */ | ||
1517 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1518 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1519 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1520 | |||
1521 | /* Setup default input to PW4 */ | ||
1522 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1523 | /* PW9 Output enable */ | ||
1524 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1525 | /* PW10 Input enable */ | ||
1526 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1527 | { } | ||
1528 | }; | ||
1529 | |||
1530 | static struct hda_verb vt1708B_4ch_volume_init_verbs[] = { | ||
1531 | /* | ||
1532 | * Unmute ADC0-1 and set the default input to mic-in | ||
1533 | */ | ||
1534 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1535 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1536 | |||
1537 | |||
1538 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
1539 | * mixer widget | ||
1540 | */ | ||
1541 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | ||
1542 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1543 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1544 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
1545 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
1546 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
1547 | |||
1548 | /* | ||
1549 | * Set up output mixers | ||
1550 | */ | ||
1551 | /* set vol=0 to output mixers */ | ||
1552 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1553 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1554 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1555 | |||
1556 | /* Setup default input of PW4 to MW0 */ | ||
1557 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1558 | /* PW9 Output enable */ | ||
1559 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1560 | /* PW10 Input enable */ | ||
1561 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1562 | { } | ||
1563 | }; | ||
1564 | |||
1565 | static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = { | ||
1566 | .substreams = 1, | ||
1567 | .channels_min = 2, | ||
1568 | .channels_max = 8, | ||
1569 | .nid = 0x10, /* NID to query formats and rates */ | ||
1570 | .ops = { | ||
1571 | .open = via_playback_pcm_open, | ||
1572 | .prepare = via_playback_pcm_prepare, | ||
1573 | .cleanup = via_playback_pcm_cleanup | ||
1574 | }, | ||
1575 | }; | ||
1576 | |||
1577 | static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = { | ||
1578 | .substreams = 1, | ||
1579 | .channels_min = 2, | ||
1580 | .channels_max = 4, | ||
1581 | .nid = 0x10, /* NID to query formats and rates */ | ||
1582 | .ops = { | ||
1583 | .open = via_playback_pcm_open, | ||
1584 | .prepare = via_playback_pcm_prepare, | ||
1585 | .cleanup = via_playback_pcm_cleanup | ||
1586 | }, | ||
1587 | }; | ||
1588 | |||
1589 | static struct hda_pcm_stream vt1708B_pcm_analog_capture = { | ||
1590 | .substreams = 2, | ||
1591 | .channels_min = 2, | ||
1592 | .channels_max = 2, | ||
1593 | .nid = 0x13, /* NID to query formats and rates */ | ||
1594 | .ops = { | ||
1595 | .prepare = via_capture_pcm_prepare, | ||
1596 | .cleanup = via_capture_pcm_cleanup | ||
1597 | }, | ||
1598 | }; | ||
1599 | |||
1600 | static struct hda_pcm_stream vt1708B_pcm_digital_playback = { | ||
1601 | .substreams = 1, | ||
1602 | .channels_min = 2, | ||
1603 | .channels_max = 2, | ||
1604 | /* NID is set in via_build_pcms */ | ||
1605 | .ops = { | ||
1606 | .open = via_dig_playback_pcm_open, | ||
1607 | .close = via_dig_playback_pcm_close, | ||
1608 | .prepare = via_dig_playback_pcm_prepare | ||
1609 | }, | ||
1610 | }; | ||
1611 | |||
1612 | static struct hda_pcm_stream vt1708B_pcm_digital_capture = { | ||
1613 | .substreams = 1, | ||
1614 | .channels_min = 2, | ||
1615 | .channels_max = 2, | ||
1616 | }; | ||
1617 | |||
1618 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
1619 | static int vt1708B_auto_fill_dac_nids(struct via_spec *spec, | ||
1620 | const struct auto_pin_cfg *cfg) | ||
1621 | { | ||
1622 | int i; | ||
1623 | hda_nid_t nid; | ||
1624 | |||
1625 | spec->multiout.num_dacs = cfg->line_outs; | ||
1626 | |||
1627 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
1628 | |||
1629 | for (i = 0; i < 4; i++) { | ||
1630 | nid = cfg->line_out_pins[i]; | ||
1631 | if (nid) { | ||
1632 | /* config dac list */ | ||
1633 | switch (i) { | ||
1634 | case AUTO_SEQ_FRONT: | ||
1635 | spec->multiout.dac_nids[i] = 0x10; | ||
1636 | break; | ||
1637 | case AUTO_SEQ_CENLFE: | ||
1638 | spec->multiout.dac_nids[i] = 0x24; | ||
1639 | break; | ||
1640 | case AUTO_SEQ_SURROUND: | ||
1641 | spec->multiout.dac_nids[i] = 0x25; | ||
1642 | break; | ||
1643 | case AUTO_SEQ_SIDE: | ||
1644 | spec->multiout.dac_nids[i] = 0x11; | ||
1645 | break; | ||
1646 | } | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | return 0; | ||
1651 | } | ||
1652 | |||
1653 | /* add playback controls from the parsed DAC table */ | ||
1654 | static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec, | ||
1655 | const struct auto_pin_cfg *cfg) | ||
1656 | { | ||
1657 | char name[32]; | ||
1658 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | ||
1659 | hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18}; | ||
1660 | hda_nid_t nid, nid_vol = 0; | ||
1661 | int i, err; | ||
1662 | |||
1663 | for (i = 0; i <= AUTO_SEQ_SIDE; i++) { | ||
1664 | nid = cfg->line_out_pins[i]; | ||
1665 | |||
1666 | if (!nid) | ||
1667 | continue; | ||
1668 | |||
1669 | nid_vol = nid_vols[i]; | ||
1670 | |||
1671 | if (i == AUTO_SEQ_CENLFE) { | ||
1672 | /* Center/LFE */ | ||
1673 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | ||
1674 | "Center Playback Volume", | ||
1675 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, | ||
1676 | HDA_OUTPUT)); | ||
1677 | if (err < 0) | ||
1678 | return err; | ||
1679 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | ||
1680 | "LFE Playback Volume", | ||
1681 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, | ||
1682 | HDA_OUTPUT)); | ||
1683 | if (err < 0) | ||
1684 | return err; | ||
1685 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | ||
1686 | "Center Playback Switch", | ||
1687 | HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, | ||
1688 | HDA_OUTPUT)); | ||
1689 | if (err < 0) | ||
1690 | return err; | ||
1691 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | ||
1692 | "LFE Playback Switch", | ||
1693 | HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, | ||
1694 | HDA_OUTPUT)); | ||
1695 | if (err < 0) | ||
1696 | return err; | ||
1697 | } else if (i == AUTO_SEQ_FRONT) { | ||
1698 | /* add control to mixer index 0 */ | ||
1699 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | ||
1700 | "Master Front Playback Volume", | ||
1701 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, | ||
1702 | HDA_INPUT)); | ||
1703 | if (err < 0) | ||
1704 | return err; | ||
1705 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | ||
1706 | "Master Front Playback Switch", | ||
1707 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, | ||
1708 | HDA_INPUT)); | ||
1709 | if (err < 0) | ||
1710 | return err; | ||
1711 | |||
1712 | /* add control to PW3 */ | ||
1713 | sprintf(name, "%s Playback Volume", chname[i]); | ||
1714 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | ||
1715 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
1716 | HDA_OUTPUT)); | ||
1717 | if (err < 0) | ||
1718 | return err; | ||
1719 | sprintf(name, "%s Playback Switch", chname[i]); | ||
1720 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | ||
1721 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
1722 | HDA_OUTPUT)); | ||
1723 | if (err < 0) | ||
1724 | return err; | ||
1725 | } else { | ||
1726 | sprintf(name, "%s Playback Volume", chname[i]); | ||
1727 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | ||
1728 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, | ||
1729 | HDA_OUTPUT)); | ||
1730 | if (err < 0) | ||
1731 | return err; | ||
1732 | sprintf(name, "%s Playback Switch", chname[i]); | ||
1733 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, | ||
1734 | HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, | ||
1735 | HDA_OUTPUT)); | ||
1736 | if (err < 0) | ||
1737 | return err; | ||
1738 | } | ||
1739 | } | ||
1740 | |||
1741 | return 0; | ||
1742 | } | ||
1743 | |||
1744 | static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | ||
1745 | { | ||
1746 | int err; | ||
1747 | |||
1748 | if (!pin) | ||
1749 | return 0; | ||
1750 | |||
1751 | spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */ | ||
1752 | |||
1753 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | ||
1754 | "Headphone Playback Volume", | ||
1755 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); | ||
1756 | if (err < 0) | ||
1757 | return err; | ||
1758 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | ||
1759 | "Headphone Playback Switch", | ||
1760 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); | ||
1761 | if (err < 0) | ||
1762 | return err; | ||
1763 | |||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | /* create playback/capture controls for input pins */ | ||
1768 | static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, | ||
1769 | const struct auto_pin_cfg *cfg) | ||
1770 | { | ||
1771 | static char *labels[] = { | ||
1772 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
1773 | }; | ||
1774 | struct hda_input_mux *imux = &spec->private_imux; | ||
1775 | int i, err, idx = 0; | ||
1776 | |||
1777 | /* for internal loopback recording select */ | ||
1778 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
1779 | imux->items[imux->num_items].index = idx; | ||
1780 | imux->num_items++; | ||
1781 | |||
1782 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
1783 | if (!cfg->input_pins[i]) | ||
1784 | continue; | ||
1785 | |||
1786 | switch (cfg->input_pins[i]) { | ||
1787 | case 0x1a: /* Mic */ | ||
1788 | idx = 2; | ||
1789 | break; | ||
1790 | |||
1791 | case 0x1b: /* Line In */ | ||
1792 | idx = 3; | ||
1793 | break; | ||
1794 | |||
1795 | case 0x1e: /* Front Mic */ | ||
1796 | idx = 4; | ||
1797 | break; | ||
1798 | |||
1799 | case 0x1f: /* CD */ | ||
1800 | idx = 1; | ||
1801 | break; | ||
1802 | } | ||
1803 | err = via_new_analog_input(spec, cfg->input_pins[i], labels[i], | ||
1804 | idx, 0x16); | ||
1805 | if (err < 0) | ||
1806 | return err; | ||
1807 | imux->items[imux->num_items].label = labels[i]; | ||
1808 | imux->items[imux->num_items].index = idx; | ||
1809 | imux->num_items++; | ||
1810 | } | ||
1811 | return 0; | ||
1812 | } | ||
1813 | |||
1814 | static int vt1708B_parse_auto_config(struct hda_codec *codec) | ||
1815 | { | ||
1816 | struct via_spec *spec = codec->spec; | ||
1817 | int err; | ||
1818 | |||
1819 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | ||
1820 | if (err < 0) | ||
1821 | return err; | ||
1822 | err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg); | ||
1823 | if (err < 0) | ||
1824 | return err; | ||
1825 | if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) | ||
1826 | return 0; /* can't find valid BIOS pin config */ | ||
1827 | |||
1828 | err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
1829 | if (err < 0) | ||
1830 | return err; | ||
1831 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | ||
1832 | if (err < 0) | ||
1833 | return err; | ||
1834 | err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
1835 | if (err < 0) | ||
1836 | return err; | ||
1837 | |||
1838 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
1839 | |||
1840 | if (spec->autocfg.dig_out_pin) | ||
1841 | spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; | ||
1842 | if (spec->autocfg.dig_in_pin) | ||
1843 | spec->dig_in_nid = VT1708B_DIGIN_NID; | ||
1844 | |||
1845 | if (spec->kctl_alloc) | ||
1846 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
1847 | |||
1848 | spec->input_mux = &spec->private_imux; | ||
1849 | |||
1850 | return 1; | ||
1851 | } | ||
1852 | |||
1853 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1854 | static struct hda_amp_list vt1708B_loopbacks[] = { | ||
1855 | { 0x16, HDA_INPUT, 1 }, | ||
1856 | { 0x16, HDA_INPUT, 2 }, | ||
1857 | { 0x16, HDA_INPUT, 3 }, | ||
1858 | { 0x16, HDA_INPUT, 4 }, | ||
1859 | { } /* end */ | ||
1860 | }; | ||
1861 | #endif | ||
1862 | |||
1863 | static int patch_vt1708B_8ch(struct hda_codec *codec) | ||
1864 | { | ||
1865 | struct via_spec *spec; | ||
1866 | int err; | ||
1867 | |||
1868 | /* create a codec specific record */ | ||
1869 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
1870 | if (spec == NULL) | ||
1871 | return -ENOMEM; | ||
1872 | |||
1873 | codec->spec = spec; | ||
1874 | |||
1875 | /* automatic parse from the BIOS config */ | ||
1876 | err = vt1708B_parse_auto_config(codec); | ||
1877 | if (err < 0) { | ||
1878 | via_free(codec); | ||
1879 | return err; | ||
1880 | } else if (!err) { | ||
1881 | printk(KERN_INFO "hda_codec: Cannot set up configuration " | ||
1882 | "from BIOS. Using genenic mode...\n"); | ||
1883 | } | ||
1884 | |||
1885 | spec->init_verbs = vt1708B_8ch_volume_init_verbs; | ||
1886 | |||
1887 | spec->stream_name_analog = "VT1708B Analog"; | ||
1888 | spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback; | ||
1889 | spec->stream_analog_capture = &vt1708B_pcm_analog_capture; | ||
1890 | |||
1891 | spec->stream_name_digital = "VT1708B Digital"; | ||
1892 | spec->stream_digital_playback = &vt1708B_pcm_digital_playback; | ||
1893 | spec->stream_digital_capture = &vt1708B_pcm_digital_capture; | ||
1894 | |||
1895 | if (!spec->adc_nids && spec->input_mux) { | ||
1896 | spec->adc_nids = vt1708B_adc_nids; | ||
1897 | spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids); | ||
1898 | spec->mixers[spec->num_mixers] = vt1708B_capture_mixer; | ||
1899 | spec->num_mixers++; | ||
1900 | } | ||
1901 | |||
1902 | codec->patch_ops = via_patch_ops; | ||
1903 | |||
1904 | codec->patch_ops.init = via_auto_init; | ||
1905 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1906 | spec->loopback.amplist = vt1708B_loopbacks; | ||
1907 | #endif | ||
1908 | |||
1909 | return 0; | ||
1910 | } | ||
1911 | |||
1912 | static int patch_vt1708B_4ch(struct hda_codec *codec) | ||
1913 | { | ||
1914 | struct via_spec *spec; | ||
1915 | int err; | ||
1916 | |||
1917 | /* create a codec specific record */ | ||
1918 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
1919 | if (spec == NULL) | ||
1920 | return -ENOMEM; | ||
1921 | |||
1922 | codec->spec = spec; | ||
1923 | |||
1924 | /* automatic parse from the BIOS config */ | ||
1925 | err = vt1708B_parse_auto_config(codec); | ||
1926 | if (err < 0) { | ||
1927 | via_free(codec); | ||
1928 | return err; | ||
1929 | } else if (!err) { | ||
1930 | printk(KERN_INFO "hda_codec: Cannot set up configuration " | ||
1931 | "from BIOS. Using genenic mode...\n"); | ||
1932 | } | ||
1933 | |||
1934 | spec->init_verbs = vt1708B_4ch_volume_init_verbs; | ||
1935 | |||
1936 | spec->stream_name_analog = "VT1708B Analog"; | ||
1937 | spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback; | ||
1938 | spec->stream_analog_capture = &vt1708B_pcm_analog_capture; | ||
1939 | |||
1940 | spec->stream_name_digital = "VT1708B Digital"; | ||
1941 | spec->stream_digital_playback = &vt1708B_pcm_digital_playback; | ||
1942 | spec->stream_digital_capture = &vt1708B_pcm_digital_capture; | ||
1943 | |||
1944 | if (!spec->adc_nids && spec->input_mux) { | ||
1945 | spec->adc_nids = vt1708B_adc_nids; | ||
1946 | spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids); | ||
1947 | spec->mixers[spec->num_mixers] = vt1708B_capture_mixer; | ||
1948 | spec->num_mixers++; | ||
1949 | } | ||
1950 | |||
1951 | codec->patch_ops = via_patch_ops; | ||
1952 | |||
1953 | codec->patch_ops.init = via_auto_init; | ||
1954 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1955 | spec->loopback.amplist = vt1708B_loopbacks; | ||
1956 | #endif | ||
1406 | 1957 | ||
1407 | return 0; | 1958 | return 0; |
1408 | } | 1959 | } |
@@ -1415,13 +1966,37 @@ struct hda_codec_preset snd_hda_preset_via[] = { | |||
1415 | { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708}, | 1966 | { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708}, |
1416 | { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708}, | 1967 | { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708}, |
1417 | { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708}, | 1968 | { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708}, |
1418 | { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch}, | 1969 | { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", |
1419 | { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch}, | 1970 | .patch = patch_vt1709_10ch}, |
1420 | { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch}, | 1971 | { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", |
1421 | { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch}, | 1972 | .patch = patch_vt1709_10ch}, |
1422 | { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch}, | 1973 | { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", |
1423 | { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch}, | 1974 | .patch = patch_vt1709_10ch}, |
1424 | { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch}, | 1975 | { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", |
1425 | { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch}, | 1976 | .patch = patch_vt1709_10ch}, |
1977 | { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", | ||
1978 | .patch = patch_vt1709_6ch}, | ||
1979 | { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", | ||
1980 | .patch = patch_vt1709_6ch}, | ||
1981 | { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", | ||
1982 | .patch = patch_vt1709_6ch}, | ||
1983 | { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", | ||
1984 | .patch = patch_vt1709_6ch}, | ||
1985 | { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch", | ||
1986 | .patch = patch_vt1708B_8ch}, | ||
1987 | { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch", | ||
1988 | .patch = patch_vt1708B_8ch}, | ||
1989 | { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch", | ||
1990 | .patch = patch_vt1708B_8ch}, | ||
1991 | { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch", | ||
1992 | .patch = patch_vt1708B_8ch}, | ||
1993 | { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch", | ||
1994 | .patch = patch_vt1708B_4ch}, | ||
1995 | { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch", | ||
1996 | .patch = patch_vt1708B_4ch}, | ||
1997 | { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch", | ||
1998 | .patch = patch_vt1708B_4ch}, | ||
1999 | { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch", | ||
2000 | .patch = patch_vt1708B_4ch}, | ||
1426 | {} /* terminator */ | 2001 | {} /* terminator */ |
1427 | }; | 2002 | }; |