aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
authorLydia Wang <lydiawang@viatech.com.cn>2011-03-23 05:57:34 -0400
committerTakashi Iwai <tiwai@suse.de>2011-03-23 06:49:51 -0400
commit11890956e948e6ed1b3e4acc11b6879db6ace01b (patch)
tree0046a8e802d0f842c263fdae252091fff6647191 /sound/pci/hda/patch_via.c
parentbc92df7fe55e49c616a003b0b77e7badf2736429 (diff)
ALSA: hda - VIA: Add support for VT1802
Add support for VT1802 codec, which is similiar with VT2002P except VT1802 has no Class-D and has some different pin widget id. Signed-off-by: Lydia Wang <lydiawang@viatech.com.cn> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c195
1 files changed, 163 insertions, 32 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index b7650a3dea0..74e2a248281 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -98,9 +98,15 @@ enum VIA_HDA_CODEC {
98 VT1716S, 98 VT1716S,
99 VT2002P, 99 VT2002P,
100 VT1812, 100 VT1812,
101 VT1802,
101 CODEC_TYPES, 102 CODEC_TYPES,
102}; 103};
103 104
105#define VT2002P_COMPATIBLE(spec) \
106 ((spec)->codec_type == VT2002P ||\
107 (spec)->codec_type == VT1812 ||\
108 (spec)->codec_type == VT1802)
109
104struct via_spec { 110struct via_spec {
105 /* codec parameterization */ 111 /* codec parameterization */
106 struct snd_kcontrol_new *mixers[6]; 112 struct snd_kcontrol_new *mixers[6];
@@ -221,6 +227,8 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
221 codec_type = VT1812; 227 codec_type = VT1812;
222 else if (dev_id == 0x0440) 228 else if (dev_id == 0x0440)
223 codec_type = VT1708S; 229 codec_type = VT1708S;
230 else if ((dev_id & 0xfff) == 0x446)
231 codec_type = VT1802;
224 else 232 else
225 codec_type = UNKNOWN; 233 codec_type = UNKNOWN;
226 return codec_type; 234 return codec_type;
@@ -749,8 +757,7 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
749 || spec->codec_type == VT1702 757 || spec->codec_type == VT1702
750 || spec->codec_type == VT1718S 758 || spec->codec_type == VT1718S
751 || spec->codec_type == VT1716S 759 || spec->codec_type == VT1716S
752 || spec->codec_type == VT2002P 760 || VT2002P_COMPATIBLE(spec)) {
753 || spec->codec_type == VT1812) {
754 activate_ctl(codec, "Headphone Playback Volume", 761 activate_ctl(codec, "Headphone Playback Volume",
755 spec->hp_independent_mode); 762 spec->hp_independent_mode);
756 activate_ctl(codec, "Headphone Playback Switch", 763 activate_ctl(codec, "Headphone Playback Switch",
@@ -788,6 +795,7 @@ static int via_hp_build(struct hda_codec *codec)
788 nid = 0x34; 795 nid = 0x34;
789 break; 796 break;
790 case VT2002P: 797 case VT2002P:
798 case VT1802:
791 nid = 0x35; 799 nid = 0x35;
792 break; 800 break;
793 case VT1812: 801 case VT1812:
@@ -1071,6 +1079,7 @@ static int is_aa_path_mute(struct hda_codec *codec)
1071 break; 1079 break;
1072 case VT2002P: 1080 case VT2002P:
1073 case VT1812: 1081 case VT1812:
1082 case VT1802:
1074 nid_mixer = 0x21; 1083 nid_mixer = 0x21;
1075 start_idx = 0; 1084 start_idx = 0;
1076 end_idx = 2; 1085 end_idx = 2;
@@ -1135,6 +1144,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
1135 break; 1144 break;
1136 case VT2002P: 1145 case VT2002P:
1137 case VT1812: 1146 case VT1812:
1147 case VT1802:
1138 verb = 0xf93; 1148 verb = 0xf93;
1139 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ 1149 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
1140 break; 1150 break;
@@ -2151,7 +2161,8 @@ static int via_auto_init(struct hda_codec *codec)
2151 via_auto_init_multi_out(codec); 2161 via_auto_init_multi_out(codec);
2152 via_auto_init_hp_out(codec); 2162 via_auto_init_hp_out(codec);
2153 via_auto_init_analog_input(codec); 2163 via_auto_init_analog_input(codec);
2154 if (spec->codec_type == VT2002P || spec->codec_type == VT1812) { 2164
2165 if (VT2002P_COMPATIBLE(spec)) {
2155 via_hp_bind_automute(codec); 2166 via_hp_bind_automute(codec);
2156 } else { 2167 } else {
2157 via_hp_automute(codec); 2168 via_hp_automute(codec);
@@ -5291,6 +5302,57 @@ static struct hda_verb vt2002P_volume_init_verbs[] = {
5291 {0x1, 0xfb8, 0x88}, 5302 {0x1, 0xfb8, 0x88},
5292 { } 5303 { }
5293}; 5304};
5305static struct hda_verb vt1802_volume_init_verbs[] = {
5306 /*
5307 * Unmute ADC0-1 and set the default input to mic-in
5308 */
5309 {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5310 {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5311
5312
5313 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
5314 * mixer widget
5315 */
5316 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
5317 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5318 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5319 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5320 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5321 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5322
5323 /* MUX Indices: Mic = 0 */
5324 {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
5325 {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
5326
5327 /* PW9 Output enable */
5328 {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
5329
5330 /* Enable Boost Volume backdoor */
5331 {0x1, 0xfb9, 0x24},
5332
5333 /* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
5334 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5335 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5336 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5337 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5338 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5339 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5340 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5341 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5342
5343 /* set MUX0/1/4/8 = 0 (AOW0) */
5344 {0x34, AC_VERB_SET_CONNECT_SEL, 0},
5345 {0x35, AC_VERB_SET_CONNECT_SEL, 0},
5346 {0x38, AC_VERB_SET_CONNECT_SEL, 0},
5347 {0x3c, AC_VERB_SET_CONNECT_SEL, 0},
5348
5349 /* set PW0 index=0 (MW0) */
5350 {0x24, AC_VERB_SET_CONNECT_SEL, 0},
5351
5352 /* Enable AOW0 to MW9 */
5353 {0x1, 0xfb8, 0x88},
5354 { }
5355};
5294 5356
5295 5357
5296static struct hda_verb vt2002P_uniwill_init_verbs[] = { 5358static struct hda_verb vt2002P_uniwill_init_verbs[] = {
@@ -5303,6 +5365,16 @@ static struct hda_verb vt2002P_uniwill_init_verbs[] = {
5303 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, 5365 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5304 { } 5366 { }
5305}; 5367};
5368static struct hda_verb vt1802_uniwill_init_verbs[] = {
5369 {0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
5370 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5371 {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
5372 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
5373 {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5374 {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5375 {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
5376 { }
5377};
5306 5378
5307static struct hda_pcm_stream vt2002P_pcm_analog_playback = { 5379static struct hda_pcm_stream vt2002P_pcm_analog_playback = {
5308 .substreams = 2, 5380 .substreams = 2,
@@ -5359,10 +5431,15 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
5359 const struct auto_pin_cfg *cfg) 5431 const struct auto_pin_cfg *cfg)
5360{ 5432{
5361 int err; 5433 int err;
5434 hda_nid_t sw_nid;
5362 5435
5363 if (!cfg->line_out_pins[0]) 5436 if (!cfg->line_out_pins[0])
5364 return -1; 5437 return -1;
5365 5438
5439 if (spec->codec_type == VT1802)
5440 sw_nid = 0x28;
5441 else
5442 sw_nid = 0x26;
5366 5443
5367 /* Line-Out: PortE */ 5444 /* Line-Out: PortE */
5368 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, 5445 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
@@ -5372,7 +5449,7 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
5372 return err; 5449 return err;
5373 err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, 5450 err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
5374 "Master Front Playback Switch", 5451 "Master Front Playback Switch",
5375 HDA_COMPOSE_AMP_VAL(0x26, 3, 0, HDA_OUTPUT)); 5452 HDA_COMPOSE_AMP_VAL(sw_nid, 3, 0, HDA_OUTPUT));
5376 if (err < 0) 5453 if (err < 0)
5377 return err; 5454 return err;
5378 5455
@@ -5507,21 +5584,41 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
5507 /* AOW0 (8h)*/ 5584 /* AOW0 (8h)*/
5508 snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); 5585 snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
5509 5586
5510 /* PW4 (26h), MW4 (1ch), MUX4(37h) */ 5587 if (spec->codec_type == VT1802) {
5511 parm = AC_PWRST_D3; 5588 /* PW4 (28h), MW4 (18h), MUX4(38h) */
5512 set_pin_power_state(codec, 0x26, &parm); 5589 parm = AC_PWRST_D3;
5513 snd_hda_codec_write(codec, 0x1c, 0, 5590 set_pin_power_state(codec, 0x28, &parm);
5514 AC_VERB_SET_POWER_STATE, parm); 5591 snd_hda_codec_write(codec, 0x18, 0,
5515 snd_hda_codec_write(codec, 0x37, 0, 5592 AC_VERB_SET_POWER_STATE, parm);
5516 AC_VERB_SET_POWER_STATE, parm); 5593 snd_hda_codec_write(codec, 0x38, 0,
5594 AC_VERB_SET_POWER_STATE, parm);
5595 } else {
5596 /* PW4 (26h), MW4 (1ch), MUX4(37h) */
5597 parm = AC_PWRST_D3;
5598 set_pin_power_state(codec, 0x26, &parm);
5599 snd_hda_codec_write(codec, 0x1c, 0,
5600 AC_VERB_SET_POWER_STATE, parm);
5601 snd_hda_codec_write(codec, 0x37, 0,
5602 AC_VERB_SET_POWER_STATE, parm);
5603 }
5517 5604
5518 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ 5605 if (spec->codec_type == VT1802) {
5519 parm = AC_PWRST_D3; 5606 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
5520 set_pin_power_state(codec, 0x25, &parm); 5607 parm = AC_PWRST_D3;
5521 snd_hda_codec_write(codec, 0x19, 0, 5608 set_pin_power_state(codec, 0x25, &parm);
5522 AC_VERB_SET_POWER_STATE, parm); 5609 snd_hda_codec_write(codec, 0x15, 0,
5523 snd_hda_codec_write(codec, 0x35, 0, 5610 AC_VERB_SET_POWER_STATE, parm);
5524 AC_VERB_SET_POWER_STATE, parm); 5611 snd_hda_codec_write(codec, 0x35, 0,
5612 AC_VERB_SET_POWER_STATE, parm);
5613 } else {
5614 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
5615 parm = AC_PWRST_D3;
5616 set_pin_power_state(codec, 0x25, &parm);
5617 snd_hda_codec_write(codec, 0x19, 0,
5618 AC_VERB_SET_POWER_STATE, parm);
5619 snd_hda_codec_write(codec, 0x35, 0,
5620 AC_VERB_SET_POWER_STATE, parm);
5621 }
5525 5622
5526 if (spec->hp_independent_mode) 5623 if (spec->hp_independent_mode)
5527 snd_hda_codec_write(codec, 0x9, 0, 5624 snd_hda_codec_write(codec, 0x9, 0,
@@ -5534,22 +5631,35 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
5534 parm = AC_PWRST_D3; 5631 parm = AC_PWRST_D3;
5535 set_pin_power_state(codec, 0x24, &parm); 5632 set_pin_power_state(codec, 0x24, &parm);
5536 parm = present ? AC_PWRST_D3 : AC_PWRST_D0; 5633 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
5537 snd_hda_codec_write(codec, 0x18, 0, 5634 if (spec->codec_type == VT1802)
5538 AC_VERB_SET_POWER_STATE, parm); 5635 snd_hda_codec_write(codec, 0x14, 0,
5636 AC_VERB_SET_POWER_STATE, parm);
5637 else
5638 snd_hda_codec_write(codec, 0x18, 0,
5639 AC_VERB_SET_POWER_STATE, parm);
5539 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); 5640 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
5540 5641
5541 /* Mono Out */ 5642 /* Mono Out */
5542 present = snd_hda_jack_detect(codec, 0x26); 5643 present = snd_hda_jack_detect(codec, 0x26);
5543 5644
5544 parm = present ? AC_PWRST_D3 : AC_PWRST_D0; 5645 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
5545 /* PW15 (31h), MW8(17h), MUX8(3bh) */ 5646 if (spec->codec_type == VT1802) {
5546 snd_hda_codec_write(codec, 0x31, 0, 5647 /* PW15 (33h), MW8(1ch), MUX8(3ch) */
5547 AC_VERB_SET_POWER_STATE, parm); 5648 snd_hda_codec_write(codec, 0x33, 0,
5548 snd_hda_codec_write(codec, 0x17, 0, 5649 AC_VERB_SET_POWER_STATE, parm);
5549 AC_VERB_SET_POWER_STATE, parm); 5650 snd_hda_codec_write(codec, 0x1c, 0,
5550 snd_hda_codec_write(codec, 0x3b, 0, 5651 AC_VERB_SET_POWER_STATE, parm);
5551 AC_VERB_SET_POWER_STATE, parm); 5652 snd_hda_codec_write(codec, 0x3c, 0,
5552 5653 AC_VERB_SET_POWER_STATE, parm);
5654 } else {
5655 /* PW15 (31h), MW8(17h), MUX8(3bh) */
5656 snd_hda_codec_write(codec, 0x31, 0,
5657 AC_VERB_SET_POWER_STATE, parm);
5658 snd_hda_codec_write(codec, 0x17, 0,
5659 AC_VERB_SET_POWER_STATE, parm);
5660 snd_hda_codec_write(codec, 0x3b, 0,
5661 AC_VERB_SET_POWER_STATE, parm);
5662 }
5553 /* MW9 (21h) */ 5663 /* MW9 (21h) */
5554 if (imux_is_smixer || !is_aa_path_mute(codec)) 5664 if (imux_is_smixer || !is_aa_path_mute(codec))
5555 snd_hda_codec_write(codec, 0x21, 0, 5665 snd_hda_codec_write(codec, 0x21, 0,
@@ -5580,14 +5690,31 @@ static int patch_vt2002P(struct hda_codec *codec)
5580 "from BIOS. Using genenic mode...\n"); 5690 "from BIOS. Using genenic mode...\n");
5581 } 5691 }
5582 5692
5583 spec->init_verbs[spec->num_iverbs++] = vt2002P_volume_init_verbs; 5693 if (spec->codec_type == VT1802)
5584 spec->init_verbs[spec->num_iverbs++] = vt2002P_uniwill_init_verbs; 5694 spec->init_verbs[spec->num_iverbs++] =
5695 vt1802_volume_init_verbs;
5696 else
5697 spec->init_verbs[spec->num_iverbs++] =
5698 vt2002P_volume_init_verbs;
5585 5699
5586 spec->stream_name_analog = "VT2002P Analog"; 5700 if (spec->codec_type == VT1802)
5701 spec->init_verbs[spec->num_iverbs++] =
5702 vt1802_uniwill_init_verbs;
5703 else
5704 spec->init_verbs[spec->num_iverbs++] =
5705 vt2002P_uniwill_init_verbs;
5706
5707 if (spec->codec_type == VT1802)
5708 spec->stream_name_analog = "VT1802 Analog";
5709 else
5710 spec->stream_name_analog = "VT2002P Analog";
5587 spec->stream_analog_playback = &vt2002P_pcm_analog_playback; 5711 spec->stream_analog_playback = &vt2002P_pcm_analog_playback;
5588 spec->stream_analog_capture = &vt2002P_pcm_analog_capture; 5712 spec->stream_analog_capture = &vt2002P_pcm_analog_capture;
5589 5713
5590 spec->stream_name_digital = "VT2002P Digital"; 5714 if (spec->codec_type == VT1802)
5715 spec->stream_name_digital = "VT1802 Digital";
5716 else
5717 spec->stream_name_digital = "VT2002P Digital";
5591 spec->stream_digital_playback = &vt2002P_pcm_digital_playback; 5718 spec->stream_digital_playback = &vt2002P_pcm_digital_playback;
5592 5719
5593 if (!spec->adc_nids && spec->input_mux) { 5720 if (!spec->adc_nids && spec->input_mux) {
@@ -6118,6 +6245,10 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
6118 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812}, 6245 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
6119 { .id = 0x11060440, .name = "VT1818S", 6246 { .id = 0x11060440, .name = "VT1818S",
6120 .patch = patch_vt1708S}, 6247 .patch = patch_vt1708S},
6248 { .id = 0x11060446, .name = "VT1802",
6249 .patch = patch_vt2002P},
6250 { .id = 0x11068446, .name = "VT1802",
6251 .patch = patch_vt2002P},
6121 {} /* terminator */ 6252 {} /* terminator */
6122}; 6253};
6123 6254