aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLydia Wang <lydiawang@viatech.com.cn>2012-12-10 05:28:11 -0500
committerTakashi Iwai <tiwai@suse.de>2012-12-10 05:45:24 -0500
commit43737e0ae97ea87285686ffd07e30c82d897beb5 (patch)
tree90c05d541c9aea63eb069e2829433480adf8ba36
parent97768a8e658605a905ba0d908d1b23b475170bed (diff)
ALSA: HDA: VIA Add support for codec VT1705CF.
Add support for new codec VT1705CF. When power on/off Audio output converter of VT1705CF, the stream tag will be cleared. But driver caches the value. So when power on Audio output converter, the update_conv_power_state() will restore the saved stream tag of it. Signed-off-by: Lydia Wang <lydiawang@viatech.com.cn> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/patch_via.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index dd8cd6af5d66..08ca407fd167 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -76,6 +76,7 @@ enum VIA_HDA_CODEC {
76 VT2002P, 76 VT2002P,
77 VT1812, 77 VT1812,
78 VT1802, 78 VT1802,
79 VT1705CF,
79 CODEC_TYPES, 80 CODEC_TYPES,
80}; 81};
81 82
@@ -220,6 +221,7 @@ struct via_spec {
220 int vt1708_hp_present; 221 int vt1708_hp_present;
221 222
222 void (*set_widgets_power_state)(struct hda_codec *codec); 223 void (*set_widgets_power_state)(struct hda_codec *codec);
224 unsigned int dac_stream_tag[4];
223 225
224 struct hda_loopback_check loopback; 226 struct hda_loopback_check loopback;
225 int num_loopbacks; 227 int num_loopbacks;
@@ -296,6 +298,8 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
296 codec_type = VT1708S; 298 codec_type = VT1708S;
297 else if ((dev_id & 0xfff) == 0x446) 299 else if ((dev_id & 0xfff) == 0x446)
298 codec_type = VT1802; 300 codec_type = VT1802;
301 else if (dev_id == 0x4760)
302 codec_type = VT1705CF;
299 else 303 else
300 codec_type = UNKNOWN; 304 codec_type = UNKNOWN;
301 return codec_type; 305 return codec_type;
@@ -711,6 +715,28 @@ static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
711 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); 715 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
712} 716}
713 717
718static void update_conv_power_state(struct hda_codec *codec, hda_nid_t nid,
719 unsigned int parm, unsigned int index)
720{
721 struct via_spec *spec = codec->spec;
722 unsigned int format;
723 if (snd_hda_codec_read(codec, nid, 0,
724 AC_VERB_GET_POWER_STATE, 0) == parm)
725 return;
726 format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
727 if (format && (spec->dac_stream_tag[index] != format))
728 spec->dac_stream_tag[index] = format;
729
730 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
731 if (parm == AC_PWRST_D0) {
732 format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
733 if (!format && (spec->dac_stream_tag[index] != format))
734 snd_hda_codec_write(codec, nid, 0,
735 AC_VERB_SET_CHANNEL_STREAMID,
736 spec->dac_stream_tag[index]);
737 }
738}
739
714static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, 740static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
715 unsigned int *affected_parm) 741 unsigned int *affected_parm)
716{ 742{
@@ -1085,6 +1111,10 @@ static void __analog_low_current_mode(struct hda_codec *codec, bool force)
1085 verb = 0xf93; 1111 verb = 0xf93;
1086 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ 1112 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
1087 break; 1113 break;
1114 case VT1705CF:
1115 verb = 0xf82;
1116 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
1117 break;
1088 default: 1118 default:
1089 return; /* other codecs are not supported */ 1119 return; /* other codecs are not supported */
1090 } 1120 }
@@ -3817,6 +3847,125 @@ static int patch_vt1812(struct hda_codec *codec)
3817 return 0; 3847 return 0;
3818} 3848}
3819 3849
3850/* patch for vt3476 */
3851
3852static const struct hda_verb vt3476_init_verbs[] = {
3853 /* Enable DMic 8/16/32K */
3854 {0x1, 0xF7B, 0x30},
3855 /* Enable Boost Volume backdoor */
3856 {0x1, 0xFB9, 0x20},
3857 /* Enable AOW-MW9 path */
3858 {0x1, 0xFB8, 0x10},
3859 { }
3860};
3861
3862static void set_widgets_power_state_vt3476(struct hda_codec *codec)
3863{
3864 struct via_spec *spec = codec->spec;
3865 int imux_is_smixer;
3866 unsigned int parm, parm2;
3867 /* MUX10 (1eh) = stereo mixer */
3868 imux_is_smixer =
3869 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
3870 /* inputs */
3871 /* PW 5/6/7 (29h/2ah/2bh) */
3872 parm = AC_PWRST_D3;
3873 set_pin_power_state(codec, 0x29, &parm);
3874 set_pin_power_state(codec, 0x2a, &parm);
3875 set_pin_power_state(codec, 0x2b, &parm);
3876 if (imux_is_smixer)
3877 parm = AC_PWRST_D0;
3878 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
3879 update_power_state(codec, 0x1e, parm);
3880 update_power_state(codec, 0x1f, parm);
3881 update_power_state(codec, 0x10, parm);
3882 update_power_state(codec, 0x11, parm);
3883
3884 /* outputs */
3885 /* PW3 (27h), MW3(37h), AOW3 (bh) */
3886 if (spec->codec_type == VT1705CF) {
3887 parm = AC_PWRST_D3;
3888 update_power_state(codec, 0x27, parm);
3889 update_power_state(codec, 0x37, parm);
3890 } else {
3891 parm = AC_PWRST_D3;
3892 set_pin_power_state(codec, 0x27, &parm);
3893 update_power_state(codec, 0x37, parm);
3894 }
3895
3896 /* PW2 (26h), MW2(36h), AOW2 (ah) */
3897 parm = AC_PWRST_D3;
3898 set_pin_power_state(codec, 0x26, &parm);
3899 update_power_state(codec, 0x36, parm);
3900 if (spec->smart51_enabled) {
3901 /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
3902 set_pin_power_state(codec, 0x2b, &parm);
3903 update_power_state(codec, 0x3b, parm);
3904 update_power_state(codec, 0x1b, parm);
3905 }
3906 update_conv_power_state(codec, 0xa, parm, 2);
3907
3908 /* PW1 (25h), MW1(35h), AOW1 (9h) */
3909 parm = AC_PWRST_D3;
3910 set_pin_power_state(codec, 0x25, &parm);
3911 update_power_state(codec, 0x35, parm);
3912 if (spec->smart51_enabled) {
3913 /* PW6(2ah), MW6(3ah), MUX6(1ah) */
3914 set_pin_power_state(codec, 0x2a, &parm);
3915 update_power_state(codec, 0x3a, parm);
3916 update_power_state(codec, 0x1a, parm);
3917 }
3918 update_conv_power_state(codec, 0x9, parm, 1);
3919
3920 /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
3921 parm = AC_PWRST_D3;
3922 set_pin_power_state(codec, 0x28, &parm);
3923 update_power_state(codec, 0x38, parm);
3924 update_power_state(codec, 0x18, parm);
3925 if (spec->hp_independent_mode)
3926 update_conv_power_state(codec, 0xb, parm, 3);
3927 parm2 = parm; /* for pin 0x0b */
3928
3929 /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
3930 parm = AC_PWRST_D3;
3931 set_pin_power_state(codec, 0x24, &parm);
3932 update_power_state(codec, 0x34, parm);
3933 if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3)
3934 parm = parm2;
3935 update_conv_power_state(codec, 0x8, parm, 0);
3936 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
3937 update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
3938}
3939
3940static int patch_vt3476(struct hda_codec *codec)
3941{
3942 struct via_spec *spec;
3943 int err;
3944
3945 /* create a codec specific record */
3946 spec = via_new_spec(codec);
3947 if (spec == NULL)
3948 return -ENOMEM;
3949
3950 spec->aa_mix_nid = 0x3f;
3951 add_secret_dac_path(codec);
3952
3953 /* automatic parse from the BIOS config */
3954 err = via_parse_auto_config(codec);
3955 if (err < 0) {
3956 via_free(codec);
3957 return err;
3958 }
3959
3960 spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
3961
3962 codec->patch_ops = via_patch_ops;
3963
3964 spec->set_widgets_power_state = set_widgets_power_state_vt3476;
3965
3966 return 0;
3967}
3968
3820/* 3969/*
3821 * patch entries 3970 * patch entries
3822 */ 3971 */
@@ -3910,6 +4059,8 @@ static const struct hda_codec_preset snd_hda_preset_via[] = {
3910 .patch = patch_vt2002P}, 4059 .patch = patch_vt2002P},
3911 { .id = 0x11068446, .name = "VT1802", 4060 { .id = 0x11068446, .name = "VT1802",
3912 .patch = patch_vt2002P}, 4061 .patch = patch_vt2002P},
4062 { .id = 0x11064760, .name = "VT1705CF",
4063 .patch = patch_vt3476},
3913 {} /* terminator */ 4064 {} /* terminator */
3914}; 4065};
3915 4066