aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLydia Wang <lydiawang@viatech.com.cn>2009-10-10 07:08:41 -0400
committerTakashi Iwai <tiwai@suse.de>2009-10-11 11:58:51 -0400
commitf3db423df84570c9950754a5771ad26f0111235f (patch)
treeb7aa721c748d26b97aae03f652114268c3809a25
parentbb3c6bfc3f7a5416d85c5dbc312e2d47fc672eef (diff)
ALSA: HDA VIA: Add VT1716S 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>
-rw-r--r--sound/pci/hda/patch_via.c648
1 files changed, 644 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 2e7e72c83a52..2977004677ec 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -87,12 +87,13 @@ enum VIA_HDA_CODEC {
87 VT1708BCE, 87 VT1708BCE,
88 VT1702, 88 VT1702,
89 VT1718S, 89 VT1718S,
90 VT1716S,
90 CODEC_TYPES, 91 CODEC_TYPES,
91}; 92};
92 93
93struct via_spec { 94struct via_spec {
94 /* codec parameterization */ 95 /* codec parameterization */
95 struct snd_kcontrol_new *mixers[4]; 96 struct snd_kcontrol_new *mixers[6];
96 unsigned int num_mixers; 97 unsigned int num_mixers;
97 98
98 struct hda_verb *init_verbs[5]; 99 struct hda_verb *init_verbs[5];
@@ -135,7 +136,7 @@ struct via_spec {
135 unsigned int hp_independent_mode; 136 unsigned int hp_independent_mode;
136 unsigned int hp_independent_mode_index; 137 unsigned int hp_independent_mode_index;
137 unsigned int smart51_enabled; 138 unsigned int smart51_enabled;
138 139 unsigned int dmic_enabled;
139 enum VIA_HDA_CODEC codec_type; 140 enum VIA_HDA_CODEC codec_type;
140 141
141 /* work to check hp jack state */ 142 /* work to check hp jack state */
@@ -179,6 +180,8 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
179 else if ((dev_id & 0xfff) == 0x428 180 else if ((dev_id & 0xfff) == 0x428
180 && (dev_id >> 12) < 8) 181 && (dev_id >> 12) < 8)
181 codec_type = VT1718S; 182 codec_type = VT1718S;
183 else if (dev_id == 0x0433 || dev_id == 0xa721)
184 codec_type = VT1716S;
182 else if (dev_id == 0x0441 || dev_id == 0x4441) 185 else if (dev_id == 0x0441 || dev_id == 0x4441)
183 codec_type = VT1718S; 186 codec_type = VT1718S;
184 else 187 else
@@ -189,6 +192,7 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
189#define VIA_HP_EVENT 0x01 192#define VIA_HP_EVENT 0x01
190#define VIA_GPIO_EVENT 0x02 193#define VIA_GPIO_EVENT 0x02
191#define VIA_JACK_EVENT 0x04 194#define VIA_JACK_EVENT 0x04
195#define VIA_MONO_EVENT 0x08
192 196
193enum { 197enum {
194 VIA_CTL_WIDGET_VOL, 198 VIA_CTL_WIDGET_VOL,
@@ -295,6 +299,11 @@ static hda_nid_t vt1718S_adc_nids[2] = {
295 0x10, 0x11 299 0x10, 0x11
296}; 300};
297 301
302static hda_nid_t vt1716S_adc_nids[2] = {
303 /* ADC1-2 */
304 0x13, 0x14
305};
306
298/* add dynamic controls */ 307/* add dynamic controls */
299static int via_add_control(struct via_spec *spec, int type, const char *name, 308static int via_add_control(struct via_spec *spec, int type, const char *name,
300 unsigned long val) 309 unsigned long val)
@@ -584,6 +593,106 @@ static void set_jack_power_state(struct hda_codec *codec)
584 snd_hda_codec_write(codec, 0xc, 0, 593 snd_hda_codec_write(codec, 0xc, 0,
585 AC_VERB_SET_POWER_STATE, parm); 594 AC_VERB_SET_POWER_STATE, parm);
586 } 595 }
596 } else if (spec->codec_type == VT1716S) {
597 unsigned int mono_out, present;
598 /* SW0 (17h) = stereo mixer */
599 imux_is_smixer = snd_hda_codec_read(
600 codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
601 /* inputs */
602 /* PW 1/2/5 (1ah/1bh/1eh) */
603 parm = AC_PWRST_D3;
604 set_pin_power_state(codec, 0x1a, &parm);
605 set_pin_power_state(codec, 0x1b, &parm);
606 set_pin_power_state(codec, 0x1e, &parm);
607 if (imux_is_smixer)
608 parm = AC_PWRST_D0;
609 /* SW0 (17h), AIW0(13h) */
610 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
611 parm);
612 snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
613 parm);
614
615 parm = AC_PWRST_D3;
616 set_pin_power_state(codec, 0x1e, &parm);
617 /* PW11 (22h) */
618 if (spec->dmic_enabled)
619 set_pin_power_state(codec, 0x22, &parm);
620 else
621 snd_hda_codec_write(
622 codec, 0x22, 0,
623 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
624
625 /* SW2(26h), AIW1(14h) */
626 snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE,
627 parm);
628 snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
629 parm);
630
631 /* outputs */
632 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
633 parm = AC_PWRST_D3;
634 set_pin_power_state(codec, 0x19, &parm);
635 /* Smart 5.1 PW2(1bh) */
636 if (spec->smart51_enabled)
637 set_pin_power_state(codec, 0x1b, &parm);
638 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
639 parm);
640 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
641 parm);
642
643 /* PW7 (23h), SW3 (27h), AOW3 (25h) */
644 parm = AC_PWRST_D3;
645 set_pin_power_state(codec, 0x23, &parm);
646 /* Smart 5.1 PW1(1ah) */
647 if (spec->smart51_enabled)
648 set_pin_power_state(codec, 0x1a, &parm);
649 snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE,
650 parm);
651
652 /* Smart 5.1 PW5(1eh) */
653 if (spec->smart51_enabled)
654 set_pin_power_state(codec, 0x1e, &parm);
655 snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE,
656 parm);
657
658 /* Mono out */
659 /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
660 present = snd_hda_codec_read(
661 codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
662 if (present)
663 mono_out = 0;
664 else {
665 present = snd_hda_codec_read(
666 codec, 0x1d, 0, AC_VERB_GET_PIN_SENSE, 0)
667 & 0x80000000;
668 if (!spec->hp_independent_mode && present)
669 mono_out = 0;
670 else
671 mono_out = 1;
672 }
673 parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
674 snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE,
675 parm);
676 snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE,
677 parm);
678 snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE,
679 parm);
680
681 /* PW 3/4 (1ch/1dh) */
682 parm = AC_PWRST_D3;
683 set_pin_power_state(codec, 0x1c, &parm);
684 set_pin_power_state(codec, 0x1d, &parm);
685 /* HP Independent Mode, power on AOW3 */
686 if (spec->hp_independent_mode)
687 snd_hda_codec_write(codec, 0x25, 0,
688 AC_VERB_SET_POWER_STATE, parm);
689
690 /* force to D0 for internal Speaker */
691 /* MW0 (16h), AOW0 (10h) */
692 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
693 imux_is_smixer ? AC_PWRST_D0 : parm);
694 snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
695 mono_out ? AC_PWRST_D0 : parm);
587 } 696 }
588} 697}
589 698
@@ -738,7 +847,8 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
738 /* update HP volume/swtich active state */ 847 /* update HP volume/swtich active state */
739 if (spec->codec_type == VT1708S 848 if (spec->codec_type == VT1708S
740 || spec->codec_type == VT1702 849 || spec->codec_type == VT1702
741 || spec->codec_type == VT1718S) { 850 || spec->codec_type == VT1718S
851 || spec->codec_type == VT1716S) {
742 activate_ctl(codec, "Headphone Playback Volume", 852 activate_ctl(codec, "Headphone Playback Volume",
743 spec->hp_independent_mode); 853 spec->hp_independent_mode);
744 activate_ctl(codec, "Headphone Playback Switch", 854 activate_ctl(codec, "Headphone Playback Switch",
@@ -797,6 +907,7 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
797 case VT1708B_8CH: 907 case VT1708B_8CH:
798 case VT1708B_4CH: 908 case VT1708B_4CH:
799 case VT1708S: 909 case VT1708S:
910 case VT1716S:
800 nid_mixer = 0x16; 911 nid_mixer = 0x16;
801 start_idx = 2; 912 start_idx = 2;
802 end_idx = 4; 913 end_idx = 4;
@@ -898,7 +1009,8 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
898 HDA_AMP_UNMUTE); 1009 HDA_AMP_UNMUTE);
899 } 1010 }
900 if (i == AUTO_PIN_FRONT_MIC) { 1011 if (i == AUTO_PIN_FRONT_MIC) {
901 if (spec->codec_type == VT1708S) { 1012 if (spec->codec_type == VT1708S
1013 || spec->codec_type == VT1716S) {
902 /* input = index 1 (AOW3) */ 1014 /* input = index 1 (AOW3) */
903 snd_hda_codec_write( 1015 snd_hda_codec_write(
904 codec, nid, 0, 1016 codec, nid, 0,
@@ -961,6 +1073,7 @@ static int is_aa_path_mute(struct hda_codec *codec)
961 case VT1708B_8CH: 1073 case VT1708B_8CH:
962 case VT1708B_4CH: 1074 case VT1708B_4CH:
963 case VT1708S: 1075 case VT1708S:
1076 case VT1716S:
964 nid_mixer = 0x16; 1077 nid_mixer = 0x16;
965 start_idx = 2; 1078 start_idx = 2;
966 end_idx = 4; 1079 end_idx = 4;
@@ -1025,6 +1138,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
1025 break; 1138 break;
1026 case VT1708S: 1139 case VT1708S:
1027 case VT1718S: 1140 case VT1718S:
1141 case VT1716S:
1028 verb = 0xf73; 1142 verb = 0xf73;
1029 parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */ 1143 parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
1030 break; 1144 break;
@@ -1453,6 +1567,36 @@ static void via_hp_automute(struct hda_codec *codec)
1453 } 1567 }
1454} 1568}
1455 1569
1570/* mute mono out if HP or Line out is plugged */
1571static void via_mono_automute(struct hda_codec *codec)
1572{
1573 unsigned int hp_present, lineout_present;
1574 struct via_spec *spec = codec->spec;
1575
1576 if (spec->codec_type != VT1716S)
1577 return;
1578
1579 lineout_present = snd_hda_codec_read(
1580 codec, spec->autocfg.line_out_pins[0], 0,
1581 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1582
1583 /* Mute Mono Out if Line Out is plugged */
1584 if (lineout_present) {
1585 snd_hda_codec_amp_stereo(
1586 codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_MUTE);
1587 return;
1588 }
1589
1590 hp_present = snd_hda_codec_read(
1591 codec, spec->autocfg.hp_pins[0], 0,
1592 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1593
1594 if (!spec->hp_independent_mode)
1595 snd_hda_codec_amp_stereo(
1596 codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE,
1597 hp_present ? HDA_AMP_MUTE : 0);
1598}
1599
1456static void via_gpio_control(struct hda_codec *codec) 1600static void via_gpio_control(struct hda_codec *codec)
1457{ 1601{
1458 unsigned int gpio_data; 1602 unsigned int gpio_data;
@@ -1512,6 +1656,8 @@ static void via_unsol_event(struct hda_codec *codec,
1512 via_gpio_control(codec); 1656 via_gpio_control(codec);
1513 if (res & VIA_JACK_EVENT) 1657 if (res & VIA_JACK_EVENT)
1514 set_jack_power_state(codec); 1658 set_jack_power_state(codec);
1659 if (res & VIA_MONO_EVENT)
1660 via_mono_automute(codec);
1515} 1661}
1516 1662
1517static int via_init(struct hda_codec *codec) 1663static int via_init(struct hda_codec *codec)
@@ -4365,6 +4511,496 @@ static int patch_vt1718S(struct hda_codec *codec)
4365 4511
4366 return 0; 4512 return 0;
4367} 4513}
4514
4515/* Patch for VT1716S */
4516
4517static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
4518 struct snd_ctl_elem_info *uinfo)
4519{
4520 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4521 uinfo->count = 1;
4522 uinfo->value.integer.min = 0;
4523 uinfo->value.integer.max = 1;
4524 return 0;
4525}
4526
4527static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
4528 struct snd_ctl_elem_value *ucontrol)
4529{
4530 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4531 int index = 0;
4532
4533 index = snd_hda_codec_read(codec, 0x26, 0,
4534 AC_VERB_GET_CONNECT_SEL, 0);
4535 if (index != -1)
4536 *ucontrol->value.integer.value = index;
4537
4538 return 0;
4539}
4540
4541static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
4542 struct snd_ctl_elem_value *ucontrol)
4543{
4544 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4545 struct via_spec *spec = codec->spec;
4546 int index = *ucontrol->value.integer.value;
4547
4548 snd_hda_codec_write(codec, 0x26, 0,
4549 AC_VERB_SET_CONNECT_SEL, index);
4550 spec->dmic_enabled = index;
4551 set_jack_power_state(codec);
4552
4553 return 1;
4554}
4555
4556/* capture mixer elements */
4557static struct snd_kcontrol_new vt1716S_capture_mixer[] = {
4558 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
4559 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
4560 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
4561 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
4562 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x1A, 0x0, HDA_INPUT),
4563 HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x1E, 0x0,
4564 HDA_INPUT),
4565 {
4566 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4567 .name = "Input Source",
4568 .count = 1,
4569 .info = via_mux_enum_info,
4570 .get = via_mux_enum_get,
4571 .put = via_mux_enum_put,
4572 },
4573 { } /* end */
4574};
4575
4576static struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
4577 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
4578 {
4579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4580 .name = "Digital Mic Capture Switch",
4581 .count = 1,
4582 .info = vt1716s_dmic_info,
4583 .get = vt1716s_dmic_get,
4584 .put = vt1716s_dmic_put,
4585 },
4586 {} /* end */
4587};
4588
4589
4590/* mono-out mixer elements */
4591static struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
4592 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
4593 { } /* end */
4594};
4595
4596static struct hda_verb vt1716S_volume_init_verbs[] = {
4597 /*
4598 * Unmute ADC0-1 and set the default input to mic-in
4599 */
4600 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4601 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4602
4603
4604 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
4605 * mixer widget
4606 */
4607 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
4608 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4609 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4610 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4611 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4612 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4613
4614 /* MUX Indices: Stereo Mixer = 5 */
4615 {0x17, AC_VERB_SET_CONNECT_SEL, 0x5},
4616
4617 /* Setup default input of PW4 to MW0 */
4618 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
4619
4620 /* Setup default input of SW1 as MW0 */
4621 {0x18, AC_VERB_SET_CONNECT_SEL, 0x1},
4622
4623 /* Setup default input of SW4 as AOW0 */
4624 {0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
4625
4626 /* PW9 PW10 Output enable */
4627 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4628 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4629
4630 /* Unmute SW1, PW12 */
4631 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4632 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4633 /* PW12 Output enable */
4634 {0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
4635 /* Enable Boost Volume backdoor */
4636 {0x1, 0xf8a, 0x80},
4637 /* don't bybass mixer */
4638 {0x1, 0xf88, 0xc0},
4639 /* Enable mono output */
4640 {0x1, 0xf90, 0x08},
4641 { }
4642};
4643
4644
4645static struct hda_verb vt1716S_uniwill_init_verbs[] = {
4646 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
4647 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
4648 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4649 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4650 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4651 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE,
4652 AC_USRSP_EN | VIA_MONO_EVENT | VIA_JACK_EVENT},
4653 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4654 {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
4655 { }
4656};
4657
4658static struct hda_pcm_stream vt1716S_pcm_analog_playback = {
4659 .substreams = 2,
4660 .channels_min = 2,
4661 .channels_max = 6,
4662 .nid = 0x10, /* NID to query formats and rates */
4663 .ops = {
4664 .open = via_playback_pcm_open,
4665 .prepare = via_playback_multi_pcm_prepare,
4666 .cleanup = via_playback_multi_pcm_cleanup,
4667 .close = via_pcm_open_close,
4668 },
4669};
4670
4671static struct hda_pcm_stream vt1716S_pcm_analog_capture = {
4672 .substreams = 2,
4673 .channels_min = 2,
4674 .channels_max = 2,
4675 .nid = 0x13, /* NID to query formats and rates */
4676 .ops = {
4677 .open = via_pcm_open_close,
4678 .prepare = via_capture_pcm_prepare,
4679 .cleanup = via_capture_pcm_cleanup,
4680 .close = via_pcm_open_close,
4681 },
4682};
4683
4684static struct hda_pcm_stream vt1716S_pcm_digital_playback = {
4685 .substreams = 2,
4686 .channels_min = 2,
4687 .channels_max = 2,
4688 .rates = SNDRV_PCM_RATE_48000,
4689 /* NID is set in via_build_pcms */
4690 .ops = {
4691 .open = via_dig_playback_pcm_open,
4692 .close = via_dig_playback_pcm_close,
4693 .prepare = via_dig_playback_pcm_prepare,
4694 .cleanup = via_dig_playback_pcm_cleanup
4695 },
4696};
4697
4698/* fill in the dac_nids table from the parsed pin configuration */
4699static int vt1716S_auto_fill_dac_nids(struct via_spec *spec,
4700 const struct auto_pin_cfg *cfg)
4701{ int i;
4702 hda_nid_t nid;
4703
4704 spec->multiout.num_dacs = cfg->line_outs;
4705
4706 spec->multiout.dac_nids = spec->private_dac_nids;
4707
4708 for (i = 0; i < 3; i++) {
4709 nid = cfg->line_out_pins[i];
4710 if (nid) {
4711 /* config dac list */
4712 switch (i) {
4713 case AUTO_SEQ_FRONT:
4714 spec->multiout.dac_nids[i] = 0x10;
4715 break;
4716 case AUTO_SEQ_CENLFE:
4717 spec->multiout.dac_nids[i] = 0x25;
4718 break;
4719 case AUTO_SEQ_SURROUND:
4720 spec->multiout.dac_nids[i] = 0x11;
4721 break;
4722 }
4723 }
4724 }
4725
4726 return 0;
4727}
4728
4729/* add playback controls from the parsed DAC table */
4730static int vt1716S_auto_create_multi_out_ctls(struct via_spec *spec,
4731 const struct auto_pin_cfg *cfg)
4732{
4733 char name[32];
4734 static const char *chname[3] = { "Front", "Surround", "C/LFE" };
4735 hda_nid_t nid_vols[] = {0x10, 0x11, 0x25};
4736 hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27};
4737 hda_nid_t nid, nid_vol, nid_mute;
4738 int i, err;
4739
4740 for (i = 0; i <= AUTO_SEQ_CENLFE; i++) {
4741 nid = cfg->line_out_pins[i];
4742
4743 if (!nid)
4744 continue;
4745
4746 nid_vol = nid_vols[i];
4747 nid_mute = nid_mutes[i];
4748
4749 if (i == AUTO_SEQ_CENLFE) {
4750 err = via_add_control(
4751 spec, VIA_CTL_WIDGET_VOL,
4752 "Center Playback Volume",
4753 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
4754 if (err < 0)
4755 return err;
4756 err = via_add_control(
4757 spec, VIA_CTL_WIDGET_VOL,
4758 "LFE Playback Volume",
4759 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
4760 if (err < 0)
4761 return err;
4762 err = via_add_control(
4763 spec, VIA_CTL_WIDGET_MUTE,
4764 "Center Playback Switch",
4765 HDA_COMPOSE_AMP_VAL(nid_mute, 1, 0,
4766 HDA_OUTPUT));
4767 if (err < 0)
4768 return err;
4769 err = via_add_control(
4770 spec, VIA_CTL_WIDGET_MUTE,
4771 "LFE Playback Switch",
4772 HDA_COMPOSE_AMP_VAL(nid_mute, 2, 0,
4773 HDA_OUTPUT));
4774 if (err < 0)
4775 return err;
4776 } else if (i == AUTO_SEQ_FRONT) {
4777
4778 err = via_add_control(
4779 spec, VIA_CTL_WIDGET_VOL,
4780 "Master Front Playback Volume",
4781 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
4782 if (err < 0)
4783 return err;
4784 err = via_add_control(
4785 spec, VIA_CTL_WIDGET_MUTE,
4786 "Master Front Playback Switch",
4787 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
4788 if (err < 0)
4789 return err;
4790
4791 sprintf(name, "%s Playback Volume", chname[i]);
4792 err = via_add_control(
4793 spec, VIA_CTL_WIDGET_VOL, name,
4794 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
4795 if (err < 0)
4796 return err;
4797 sprintf(name, "%s Playback Switch", chname[i]);
4798 err = via_add_control(
4799 spec, VIA_CTL_WIDGET_MUTE, name,
4800 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
4801 HDA_OUTPUT));
4802 if (err < 0)
4803 return err;
4804 } else {
4805 sprintf(name, "%s Playback Volume", chname[i]);
4806 err = via_add_control(
4807 spec, VIA_CTL_WIDGET_VOL, name,
4808 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
4809 if (err < 0)
4810 return err;
4811 sprintf(name, "%s Playback Switch", chname[i]);
4812 err = via_add_control(
4813 spec, VIA_CTL_WIDGET_MUTE, name,
4814 HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
4815 HDA_OUTPUT));
4816 if (err < 0)
4817 return err;
4818 }
4819 }
4820 return 0;
4821}
4822
4823static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
4824{
4825 int err;
4826
4827 if (!pin)
4828 return 0;
4829
4830 spec->multiout.hp_nid = 0x25; /* AOW3 */
4831 spec->hp_independent_mode_index = 1;
4832
4833 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
4834 "Headphone Playback Volume",
4835 HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
4836 if (err < 0)
4837 return err;
4838
4839 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
4840 "Headphone Playback Switch",
4841 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4842 if (err < 0)
4843 return err;
4844
4845 create_hp_imux(spec);
4846 return 0;
4847}
4848
4849/* create playback/capture controls for input pins */
4850static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec,
4851 const struct auto_pin_cfg *cfg)
4852{
4853 static char *labels[] = {
4854 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
4855 };
4856 struct hda_input_mux *imux = &spec->private_imux[0];
4857 int i, err, idx = 0;
4858
4859 /* for internal loopback recording select */
4860 imux->items[imux->num_items].label = "Stereo Mixer";
4861 imux->items[imux->num_items].index = 5;
4862 imux->num_items++;
4863
4864 for (i = 0; i < AUTO_PIN_LAST; i++) {
4865 if (!cfg->input_pins[i])
4866 continue;
4867
4868 switch (cfg->input_pins[i]) {
4869 case 0x1a: /* Mic */
4870 idx = 2;
4871 break;
4872
4873 case 0x1b: /* Line In */
4874 idx = 3;
4875 break;
4876
4877 case 0x1e: /* Front Mic */
4878 idx = 4;
4879 break;
4880
4881 case 0x1f: /* CD */
4882 idx = 1;
4883 break;
4884 }
4885 err = via_new_analog_input(spec, labels[i], idx, 0x16);
4886 if (err < 0)
4887 return err;
4888 imux->items[imux->num_items].label = labels[i];
4889 imux->items[imux->num_items].index = idx-1;
4890 imux->num_items++;
4891 }
4892 return 0;
4893}
4894
4895static int vt1716S_parse_auto_config(struct hda_codec *codec)
4896{
4897 struct via_spec *spec = codec->spec;
4898 int err;
4899
4900 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
4901 if (err < 0)
4902 return err;
4903 err = vt1716S_auto_fill_dac_nids(spec, &spec->autocfg);
4904 if (err < 0)
4905 return err;
4906 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
4907 return 0; /* can't find valid BIOS pin config */
4908
4909 err = vt1716S_auto_create_multi_out_ctls(spec, &spec->autocfg);
4910 if (err < 0)
4911 return err;
4912 err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
4913 if (err < 0)
4914 return err;
4915 err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg);
4916 if (err < 0)
4917 return err;
4918
4919 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4920
4921 fill_dig_outs(codec);
4922
4923 if (spec->kctls.list)
4924 spec->mixers[spec->num_mixers++] = spec->kctls.list;
4925
4926 spec->input_mux = &spec->private_imux[0];
4927
4928 if (spec->hp_mux)
4929 spec->mixers[spec->num_mixers++] = via_hp_mixer;
4930
4931 spec->mixers[spec->num_mixers++] = via_smart51_mixer;
4932
4933 return 1;
4934}
4935
4936#ifdef CONFIG_SND_HDA_POWER_SAVE
4937static struct hda_amp_list vt1716S_loopbacks[] = {
4938 { 0x16, HDA_INPUT, 1 },
4939 { 0x16, HDA_INPUT, 2 },
4940 { 0x16, HDA_INPUT, 3 },
4941 { 0x16, HDA_INPUT, 4 },
4942 { } /* end */
4943};
4944#endif
4945
4946static int patch_vt1716S(struct hda_codec *codec)
4947{
4948 struct via_spec *spec;
4949 int err;
4950
4951 /* create a codec specific record */
4952 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4953 if (spec == NULL)
4954 return -ENOMEM;
4955
4956 codec->spec = spec;
4957
4958 /* automatic parse from the BIOS config */
4959 err = vt1716S_parse_auto_config(codec);
4960 if (err < 0) {
4961 via_free(codec);
4962 return err;
4963 } else if (!err) {
4964 printk(KERN_INFO "hda_codec: Cannot set up configuration "
4965 "from BIOS. Using genenic mode...\n");
4966 }
4967
4968 spec->init_verbs[spec->num_iverbs++] = vt1716S_volume_init_verbs;
4969 spec->init_verbs[spec->num_iverbs++] = vt1716S_uniwill_init_verbs;
4970
4971 spec->stream_name_analog = "VT1716S Analog";
4972 spec->stream_analog_playback = &vt1716S_pcm_analog_playback;
4973 spec->stream_analog_capture = &vt1716S_pcm_analog_capture;
4974
4975 spec->stream_name_digital = "VT1716S Digital";
4976 spec->stream_digital_playback = &vt1716S_pcm_digital_playback;
4977
4978 if (!spec->adc_nids && spec->input_mux) {
4979 spec->adc_nids = vt1716S_adc_nids;
4980 spec->num_adc_nids = ARRAY_SIZE(vt1716S_adc_nids);
4981 get_mux_nids(codec);
4982 override_mic_boost(codec, 0x1a, 0, 3, 40);
4983 override_mic_boost(codec, 0x1e, 0, 3, 40);
4984 spec->mixers[spec->num_mixers] = vt1716S_capture_mixer;
4985 spec->num_mixers++;
4986 }
4987
4988 spec->mixers[spec->num_mixers] = vt1716s_dmic_mixer;
4989 spec->num_mixers++;
4990
4991 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
4992
4993 codec->patch_ops = via_patch_ops;
4994
4995 codec->patch_ops.init = via_auto_init;
4996 codec->patch_ops.unsol_event = via_unsol_event,
4997
4998#ifdef CONFIG_SND_HDA_POWER_SAVE
4999 spec->loopback.amplist = vt1716S_loopbacks;
5000#endif
5001
5002 return 0;
5003}
4368/* 5004/*
4369 * patch entries 5005 * patch entries
4370 */ 5006 */
@@ -4445,6 +5081,10 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
4445 .patch = patch_vt1718S}, 5081 .patch = patch_vt1718S},
4446 { .id = 0x11064441, .name = "VT1828S", 5082 { .id = 0x11064441, .name = "VT1828S",
4447 .patch = patch_vt1718S}, 5083 .patch = patch_vt1718S},
5084 { .id = 0x11060433, .name = "VT1716S",
5085 .patch = patch_vt1716S},
5086 { .id = 0x1106a721, .name = "VT1716S",
5087 .patch = patch_vt1716S},
4448 {} /* terminator */ 5088 {} /* terminator */
4449}; 5089};
4450 5090