aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorLydia Wang <lydiawang@viatech.com.cn>2009-10-10 07:08:46 -0400
committerTakashi Iwai <tiwai@suse.de>2009-10-11 11:59:06 -0400
commitab6734e7ea32e9f9cbe0f55eeddf4aa629ed1c3d (patch)
tree47b0ff23a2ce43784df122cd03a7ba30819d1942 /sound/pci
parent25eaba2f8a6877ba6f58197c4723c2433a316e09 (diff)
ALSA: HDA VIA: Add VT1812 support.
Signed-off-by: Lydia Wang <lydiawang@viatech.com.cn> Signed-off-by: Logan Li <loganli@viatech.com.cn> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_via.c494
1 files changed, 491 insertions, 3 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index a94cc91c18ff..b3c5e8a78154 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -89,6 +89,7 @@ enum VIA_HDA_CODEC {
89 VT1718S, 89 VT1718S,
90 VT1716S, 90 VT1716S,
91 VT2002P, 91 VT2002P,
92 VT1812,
92 CODEC_TYPES, 93 CODEC_TYPES,
93}; 94};
94 95
@@ -187,6 +188,8 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
187 codec_type = VT1718S; 188 codec_type = VT1718S;
188 else if (dev_id == 0x0438 || dev_id == 0x4438) 189 else if (dev_id == 0x0438 || dev_id == 0x4438)
189 codec_type = VT2002P; 190 codec_type = VT2002P;
191 else if (dev_id == 0x0448)
192 codec_type = VT1812;
190 else 193 else
191 codec_type = UNKNOWN; 194 codec_type = UNKNOWN;
192 return codec_type; 195 return codec_type;
@@ -411,6 +414,12 @@ static hda_nid_t vt2002P_adc_nids[2] = {
411 0x10, 0x11 414 0x10, 0x11
412}; 415};
413 416
417static hda_nid_t vt1812_adc_nids[2] = {
418 /* ADC1-2 */
419 0x10, 0x11
420};
421
422
414/* add dynamic controls */ 423/* add dynamic controls */
415static int via_add_control(struct via_spec *spec, int type, const char *name, 424static int via_add_control(struct via_spec *spec, int type, const char *name,
416 unsigned long val) 425 unsigned long val)
@@ -904,6 +913,120 @@ static void set_jack_power_state(struct hda_codec *codec)
904 snd_hda_codec_write( 913 snd_hda_codec_write(
905 codec, 0x21, 0, 914 codec, 0x21, 0,
906 AC_VERB_SET_POWER_STATE, AC_PWRST_D3); 915 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
916 } else if (spec->codec_type == VT1812) {
917 unsigned int present;
918 /* MUX10 (1eh) = stereo mixer */
919 imux_is_smixer = snd_hda_codec_read(
920 codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
921 /* inputs */
922 /* PW 5/6/7 (29h/2ah/2bh) */
923 parm = AC_PWRST_D3;
924 set_pin_power_state(codec, 0x29, &parm);
925 set_pin_power_state(codec, 0x2a, &parm);
926 set_pin_power_state(codec, 0x2b, &parm);
927 if (imux_is_smixer)
928 parm = AC_PWRST_D0;
929 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
930 snd_hda_codec_write(codec, 0x1e, 0,
931 AC_VERB_SET_POWER_STATE, parm);
932 snd_hda_codec_write(codec, 0x1f, 0,
933 AC_VERB_SET_POWER_STATE, parm);
934 snd_hda_codec_write(codec, 0x10, 0,
935 AC_VERB_SET_POWER_STATE, parm);
936 snd_hda_codec_write(codec, 0x11, 0,
937 AC_VERB_SET_POWER_STATE, parm);
938
939 /* outputs */
940 /* AOW0 (8h)*/
941 snd_hda_codec_write(codec, 0x8, 0,
942 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
943
944 /* PW4 (28h), MW4 (18h), MUX4(38h) */
945 parm = AC_PWRST_D3;
946 set_pin_power_state(codec, 0x28, &parm);
947 snd_hda_codec_write(codec, 0x18, 0,
948 AC_VERB_SET_POWER_STATE, parm);
949 snd_hda_codec_write(codec, 0x38, 0,
950 AC_VERB_SET_POWER_STATE, parm);
951
952 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
953 parm = AC_PWRST_D3;
954 set_pin_power_state(codec, 0x25, &parm);
955 snd_hda_codec_write(codec, 0x15, 0,
956 AC_VERB_SET_POWER_STATE, parm);
957 snd_hda_codec_write(codec, 0x35, 0,
958 AC_VERB_SET_POWER_STATE, parm);
959 if (spec->hp_independent_mode) {
960 snd_hda_codec_write(codec, 0x9, 0,
961 AC_VERB_SET_POWER_STATE, parm);
962 }
963
964 /* Internal Speaker */
965 /* PW0 (24h), MW0(14h), MUX0(34h) */
966 present = snd_hda_codec_read(
967 codec, 0x25, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
968 parm = AC_PWRST_D3;
969 set_pin_power_state(codec, 0x24, &parm);
970 if (present) {
971 snd_hda_codec_write(codec, 0x14, 0,
972 AC_VERB_SET_POWER_STATE,
973 AC_PWRST_D3);
974 snd_hda_codec_write(codec, 0x34, 0,
975 AC_VERB_SET_POWER_STATE,
976 AC_PWRST_D3);
977 } else {
978 snd_hda_codec_write(codec, 0x14, 0,
979 AC_VERB_SET_POWER_STATE,
980 AC_PWRST_D0);
981 snd_hda_codec_write(codec, 0x34, 0,
982 AC_VERB_SET_POWER_STATE,
983 AC_PWRST_D0);
984 }
985 /* Mono Out */
986 /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
987 present = snd_hda_codec_read(
988 codec, 0x28, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
989 parm = AC_PWRST_D3;
990 set_pin_power_state(codec, 0x31, &parm);
991 if (present) {
992 snd_hda_codec_write(codec, 0x1c, 0,
993 AC_VERB_SET_POWER_STATE,
994 AC_PWRST_D3);
995 snd_hda_codec_write(codec, 0x3c, 0,
996 AC_VERB_SET_POWER_STATE,
997 AC_PWRST_D3);
998 snd_hda_codec_write(codec, 0x3e, 0,
999 AC_VERB_SET_POWER_STATE,
1000 AC_PWRST_D3);
1001 } else {
1002 snd_hda_codec_write(codec, 0x1c, 0,
1003 AC_VERB_SET_POWER_STATE,
1004 AC_PWRST_D0);
1005 snd_hda_codec_write(codec, 0x3c, 0,
1006 AC_VERB_SET_POWER_STATE,
1007 AC_PWRST_D0);
1008 snd_hda_codec_write(codec, 0x3e, 0,
1009 AC_VERB_SET_POWER_STATE,
1010 AC_PWRST_D0);
1011 }
1012
1013 /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
1014 parm = AC_PWRST_D3;
1015 set_pin_power_state(codec, 0x33, &parm);
1016 snd_hda_codec_write(codec, 0x1d, 0,
1017 AC_VERB_SET_POWER_STATE, parm);
1018 snd_hda_codec_write(codec, 0x3d, 0,
1019 AC_VERB_SET_POWER_STATE, parm);
1020
1021 /* MW9 (21h) */
1022 if (imux_is_smixer || !is_aa_path_mute(codec))
1023 snd_hda_codec_write(
1024 codec, 0x21, 0,
1025 AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
1026 else
1027 snd_hda_codec_write(
1028 codec, 0x21, 0,
1029 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
907 } 1030 }
908} 1031}
909 1032
@@ -974,6 +1097,9 @@ static int via_independent_hp_get(struct snd_kcontrol *kcontrol,
974 case VT2002P: 1097 case VT2002P:
975 nid = 0x35; 1098 nid = 0x35;
976 break; 1099 break;
1100 case VT1812:
1101 nid = 0x3d;
1102 break;
977 default: 1103 default:
978 nid = spec->autocfg.hp_pins[0]; 1104 nid = spec->autocfg.hp_pins[0];
979 break; 1105 break;
@@ -1049,6 +1175,9 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
1049 case VT2002P: 1175 case VT2002P:
1050 nid = 0x35; 1176 nid = 0x35;
1051 break; 1177 break;
1178 case VT1812:
1179 nid = 0x3d;
1180 break;
1052 default: 1181 default:
1053 nid = spec->autocfg.hp_pins[0]; 1182 nid = spec->autocfg.hp_pins[0];
1054 break; 1183 break;
@@ -1066,7 +1195,8 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
1066 || spec->codec_type == VT1702 1195 || spec->codec_type == VT1702
1067 || spec->codec_type == VT1718S 1196 || spec->codec_type == VT1718S
1068 || spec->codec_type == VT1716S 1197 || spec->codec_type == VT1716S
1069 || spec->codec_type == VT2002P) { 1198 || spec->codec_type == VT2002P
1199 || spec->codec_type == VT1812) {
1070 activate_ctl(codec, "Headphone Playback Volume", 1200 activate_ctl(codec, "Headphone Playback Volume",
1071 spec->hp_independent_mode); 1201 spec->hp_independent_mode);
1072 activate_ctl(codec, "Headphone Playback Switch", 1202 activate_ctl(codec, "Headphone Playback Switch",
@@ -1307,6 +1437,7 @@ static int is_aa_path_mute(struct hda_codec *codec)
1307 end_idx = 3; 1437 end_idx = 3;
1308 break; 1438 break;
1309 case VT2002P: 1439 case VT2002P:
1440 case VT1812:
1310 nid_mixer = 0x21; 1441 nid_mixer = 0x21;
1311 start_idx = 0; 1442 start_idx = 0;
1312 end_idx = 2; 1443 end_idx = 2;
@@ -1370,6 +1501,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
1370 parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */ 1501 parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
1371 break; 1502 break;
1372 case VT2002P: 1503 case VT2002P:
1504 case VT1812:
1373 verb = 0xf93; 1505 verb = 0xf93;
1374 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ 1506 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
1375 break; 1507 break;
@@ -1878,7 +2010,7 @@ static void via_speaker_automute(struct hda_codec *codec)
1878 unsigned int hp_present; 2010 unsigned int hp_present;
1879 struct via_spec *spec = codec->spec; 2011 struct via_spec *spec = codec->spec;
1880 2012
1881 if (spec->codec_type != VT2002P) 2013 if (spec->codec_type != VT2002P && spec->codec_type != VT1812)
1882 return; 2014 return;
1883 2015
1884 hp_present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0, 2016 hp_present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0,
@@ -2364,7 +2496,7 @@ static int via_auto_init(struct hda_codec *codec)
2364 via_auto_init_multi_out(codec); 2496 via_auto_init_multi_out(codec);
2365 via_auto_init_hp_out(codec); 2497 via_auto_init_hp_out(codec);
2366 via_auto_init_analog_input(codec); 2498 via_auto_init_analog_input(codec);
2367 if (spec->codec_type == VT2002P) { 2499 if (spec->codec_type == VT2002P || spec->codec_type == VT1812) {
2368 via_hp_bind_automute(codec); 2500 via_hp_bind_automute(codec);
2369 } else { 2501 } else {
2370 via_hp_automute(codec); 2502 via_hp_automute(codec);
@@ -5654,6 +5786,361 @@ static int patch_vt2002P(struct hda_codec *codec)
5654 5786
5655 return 0; 5787 return 0;
5656} 5788}
5789
5790/* for vt1812 */
5791
5792/* capture mixer elements */
5793static struct snd_kcontrol_new vt1812_capture_mixer[] = {
5794 HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
5795 HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
5796 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
5797 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
5798 HDA_CODEC_MUTE("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
5799 HDA_CODEC_MUTE("Front Mic Boost Capture Volume", 0x29, 0x0,
5800 HDA_INPUT),
5801 {
5802 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5803 /* The multiple "Capture Source" controls confuse alsamixer
5804 * So call somewhat different..
5805 */
5806 .name = "Input Source",
5807 .count = 2,
5808 .info = via_mux_enum_info,
5809 .get = via_mux_enum_get,
5810 .put = via_mux_enum_put,
5811 },
5812 { } /* end */
5813};
5814
5815static struct hda_verb vt1812_volume_init_verbs[] = {
5816 /*
5817 * Unmute ADC0-1 and set the default input to mic-in
5818 */
5819 {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5820 {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5821
5822
5823 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5824 * mixer widget
5825 */
5826 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
5827 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5828 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5829 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5830 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5831 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5832
5833 /* MUX Indices: Mic = 0 */
5834 {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
5835 {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
5836
5837 /* PW9 Output enable */
5838 {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
5839
5840 /* Enable Boost Volume backdoor */
5841 {0x1, 0xfb9, 0x24},
5842
5843 /* MW0/1/4/13/15: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
5844 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5845 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5846 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5847 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5848 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5849 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5850 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5851 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5852 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5853 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5854
5855 /* set MUX0/1/4/13/15 = 0 (AOW0) */
5856 {0x34, AC_VERB_SET_CONNECT_SEL, 0},
5857 {0x35, AC_VERB_SET_CONNECT_SEL, 0},
5858 {0x38, AC_VERB_SET_CONNECT_SEL, 0},
5859 {0x3c, AC_VERB_SET_CONNECT_SEL, 0},
5860 {0x3d, AC_VERB_SET_CONNECT_SEL, 0},
5861
5862 /* Enable AOW0 to MW9 */
5863 {0x1, 0xfb8, 0xa8},
5864 { }
5865};
5866
5867
5868static struct hda_verb vt1812_uniwill_init_verbs[] = {
5869 {0x33, AC_VERB_SET_UNSOLICITED_ENABLE,
5870 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5871 {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT },
5872 {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
5873 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5874 {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5875 {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5876 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5877 { }
5878};
5879
5880static struct hda_pcm_stream vt1812_pcm_analog_playback = {
5881 .substreams = 2,
5882 .channels_min = 2,
5883 .channels_max = 2,
5884 .nid = 0x8, /* NID to query formats and rates */
5885 .ops = {
5886 .open = via_playback_pcm_open,
5887 .prepare = via_playback_multi_pcm_prepare,
5888 .cleanup = via_playback_multi_pcm_cleanup,
5889 .close = via_pcm_open_close,
5890 },
5891};
5892
5893static struct hda_pcm_stream vt1812_pcm_analog_capture = {
5894 .substreams = 2,
5895 .channels_min = 2,
5896 .channels_max = 2,
5897 .nid = 0x10, /* NID to query formats and rates */
5898 .ops = {
5899 .open = via_pcm_open_close,
5900 .prepare = via_capture_pcm_prepare,
5901 .cleanup = via_capture_pcm_cleanup,
5902 .close = via_pcm_open_close,
5903 },
5904};
5905
5906static struct hda_pcm_stream vt1812_pcm_digital_playback = {
5907 .substreams = 1,
5908 .channels_min = 2,
5909 .channels_max = 2,
5910 .rates = SNDRV_PCM_RATE_48000,
5911 /* NID is set in via_build_pcms */
5912 .ops = {
5913 .open = via_dig_playback_pcm_open,
5914 .close = via_dig_playback_pcm_close,
5915 .prepare = via_dig_playback_pcm_prepare,
5916 .cleanup = via_dig_playback_pcm_cleanup
5917 },
5918};
5919/* fill in the dac_nids table from the parsed pin configuration */
5920static int vt1812_auto_fill_dac_nids(struct via_spec *spec,
5921 const struct auto_pin_cfg *cfg)
5922{
5923 spec->multiout.num_dacs = 1;
5924 spec->multiout.dac_nids = spec->private_dac_nids;
5925 if (cfg->line_out_pins[0])
5926 spec->multiout.dac_nids[0] = 0x8;
5927 return 0;
5928}
5929
5930
5931/* add playback controls from the parsed DAC table */
5932static int vt1812_auto_create_multi_out_ctls(struct via_spec *spec,
5933 const struct auto_pin_cfg *cfg)
5934{
5935 int err;
5936
5937 if (!cfg->line_out_pins[0])
5938 return -1;
5939
5940 /* Line-Out: PortE */
5941 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5942 "Master Front Playback Volume",
5943 HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT));
5944 if (err < 0)
5945 return err;
5946 err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
5947 "Master Front Playback Switch",
5948 HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT));
5949 if (err < 0)
5950 return err;
5951
5952 return 0;
5953}
5954
5955static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5956{
5957 int err;
5958
5959 if (!pin)
5960 return 0;
5961
5962 spec->multiout.hp_nid = 0x9;
5963 spec->hp_independent_mode_index = 1;
5964
5965
5966 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
5967 "Headphone Playback Volume",
5968 HDA_COMPOSE_AMP_VAL(
5969 spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
5970 if (err < 0)
5971 return err;
5972
5973 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
5974 "Headphone Playback Switch",
5975 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5976 if (err < 0)
5977 return err;
5978
5979 create_hp_imux(spec);
5980 return 0;
5981}
5982
5983/* create playback/capture controls for input pins */
5984static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec,
5985 const struct auto_pin_cfg *cfg)
5986{
5987 static char *labels[] = {
5988 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
5989 };
5990 struct hda_input_mux *imux = &spec->private_imux[0];
5991 int i, err, idx = 0;
5992
5993 for (i = 0; i < AUTO_PIN_LAST; i++) {
5994 if (!cfg->input_pins[i])
5995 continue;
5996
5997 switch (cfg->input_pins[i]) {
5998 case 0x2b: /* Mic */
5999 idx = 0;
6000 break;
6001
6002 case 0x2a: /* Line In */
6003 idx = 1;
6004 break;
6005
6006 case 0x29: /* Front Mic */
6007 idx = 2;
6008 break;
6009 }
6010 err = via_new_analog_input(spec, labels[i], idx, 0x21);
6011 if (err < 0)
6012 return err;
6013 imux->items[imux->num_items].label = labels[i];
6014 imux->items[imux->num_items].index = idx;
6015 imux->num_items++;
6016 }
6017 /* build volume/mute control of loopback */
6018 err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21);
6019 if (err < 0)
6020 return err;
6021
6022 /* for internal loopback recording select */
6023 imux->items[imux->num_items].label = "Stereo Mixer";
6024 imux->items[imux->num_items].index = 5;
6025 imux->num_items++;
6026
6027 /* for digital mic select */
6028 imux->items[imux->num_items].label = "Digital Mic";
6029 imux->items[imux->num_items].index = 6;
6030 imux->num_items++;
6031
6032 return 0;
6033}
6034
6035static int vt1812_parse_auto_config(struct hda_codec *codec)
6036{
6037 struct via_spec *spec = codec->spec;
6038 int err;
6039
6040
6041 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
6042 if (err < 0)
6043 return err;
6044 fill_dig_outs(codec);
6045 err = vt1812_auto_fill_dac_nids(spec, &spec->autocfg);
6046 if (err < 0)
6047 return err;
6048
6049 if (!spec->autocfg.line_outs && !spec->autocfg.hp_outs)
6050 return 0; /* can't find valid BIOS pin config */
6051
6052 err = vt1812_auto_create_multi_out_ctls(spec, &spec->autocfg);
6053 if (err < 0)
6054 return err;
6055 err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
6056 if (err < 0)
6057 return err;
6058 err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg);
6059 if (err < 0)
6060 return err;
6061
6062 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
6063
6064 fill_dig_outs(codec);
6065
6066 if (spec->kctls.list)
6067 spec->mixers[spec->num_mixers++] = spec->kctls.list;
6068
6069 spec->input_mux = &spec->private_imux[0];
6070
6071 if (spec->hp_mux)
6072 spec->mixers[spec->num_mixers++] = via_hp_mixer;
6073
6074 return 1;
6075}
6076
6077#ifdef CONFIG_SND_HDA_POWER_SAVE
6078static struct hda_amp_list vt1812_loopbacks[] = {
6079 { 0x21, HDA_INPUT, 0 },
6080 { 0x21, HDA_INPUT, 1 },
6081 { 0x21, HDA_INPUT, 2 },
6082 { } /* end */
6083};
6084#endif
6085
6086
6087/* patch for vt1812 */
6088static int patch_vt1812(struct hda_codec *codec)
6089{
6090 struct via_spec *spec;
6091 int err;
6092
6093 /* create a codec specific record */
6094 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6095 if (spec == NULL)
6096 return -ENOMEM;
6097
6098 codec->spec = spec;
6099
6100 /* automatic parse from the BIOS config */
6101 err = vt1812_parse_auto_config(codec);
6102 if (err < 0) {
6103 via_free(codec);
6104 return err;
6105 } else if (!err) {
6106 printk(KERN_INFO "hda_codec: Cannot set up configuration "
6107 "from BIOS. Using genenic mode...\n");
6108 }
6109
6110
6111 spec->init_verbs[spec->num_iverbs++] = vt1812_volume_init_verbs;
6112 spec->init_verbs[spec->num_iverbs++] = vt1812_uniwill_init_verbs;
6113
6114 spec->stream_name_analog = "VT1812 Analog";
6115 spec->stream_analog_playback = &vt1812_pcm_analog_playback;
6116 spec->stream_analog_capture = &vt1812_pcm_analog_capture;
6117
6118 spec->stream_name_digital = "VT1812 Digital";
6119 spec->stream_digital_playback = &vt1812_pcm_digital_playback;
6120
6121
6122 if (!spec->adc_nids && spec->input_mux) {
6123 spec->adc_nids = vt1812_adc_nids;
6124 spec->num_adc_nids = ARRAY_SIZE(vt1812_adc_nids);
6125 get_mux_nids(codec);
6126 override_mic_boost(codec, 0x2b, 0, 3, 40);
6127 override_mic_boost(codec, 0x29, 0, 3, 40);
6128 spec->mixers[spec->num_mixers] = vt1812_capture_mixer;
6129 spec->num_mixers++;
6130 }
6131
6132 codec->patch_ops = via_patch_ops;
6133
6134 codec->patch_ops.init = via_auto_init;
6135 codec->patch_ops.unsol_event = via_unsol_event,
6136
6137#ifdef CONFIG_SND_HDA_POWER_SAVE
6138 spec->loopback.amplist = vt1812_loopbacks;
6139#endif
6140
6141 return 0;
6142}
6143
5657/* 6144/*
5658 * patch entries 6145 * patch entries
5659 */ 6146 */
@@ -5740,6 +6227,7 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
5740 .patch = patch_vt1716S}, 6227 .patch = patch_vt1716S},
5741 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P}, 6228 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
5742 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P}, 6229 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
6230 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
5743 {} /* terminator */ 6231 {} /* terminator */
5744}; 6232};
5745 6233