diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_via.c | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 59a173e88128..63e4871e5d8f 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -35,6 +35,7 @@ | |||
35 | /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ | 35 | /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ |
36 | /* 2008-04-09 Lydia Wang Add Independent HP feature */ | 36 | /* 2008-04-09 Lydia Wang Add Independent HP feature */ |
37 | /* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */ | 37 | /* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */ |
38 | /* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */ | ||
38 | /* */ | 39 | /* */ |
39 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 40 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
40 | 41 | ||
@@ -87,6 +88,48 @@ | |||
87 | #define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397) | 88 | #define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397) |
88 | #define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398) | 89 | #define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398) |
89 | 90 | ||
91 | enum VIA_HDA_CODEC { | ||
92 | UNKNOWN = -1, | ||
93 | VT1708, | ||
94 | VT1709_10CH, | ||
95 | VT1709_6CH, | ||
96 | VT1708B_8CH, | ||
97 | VT1708B_4CH, | ||
98 | VT1708S, | ||
99 | VT1702, | ||
100 | CODEC_TYPES, | ||
101 | }; | ||
102 | |||
103 | static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id) | ||
104 | { | ||
105 | u16 ven_id = vendor_id >> 16; | ||
106 | u16 dev_id = vendor_id & 0xffff; | ||
107 | enum VIA_HDA_CODEC codec_type; | ||
108 | |||
109 | /* get codec type */ | ||
110 | if (ven_id != 0x1106) | ||
111 | codec_type = UNKNOWN; | ||
112 | else if (dev_id >= 0x1708 && dev_id <= 0x170b) | ||
113 | codec_type = VT1708; | ||
114 | else if (dev_id >= 0xe710 && dev_id <= 0xe713) | ||
115 | codec_type = VT1709_10CH; | ||
116 | else if (dev_id >= 0xe714 && dev_id <= 0xe717) | ||
117 | codec_type = VT1709_6CH; | ||
118 | else if (dev_id >= 0xe720 && dev_id <= 0xe723) | ||
119 | codec_type = VT1708B_8CH; | ||
120 | else if (dev_id >= 0xe724 && dev_id <= 0xe727) | ||
121 | codec_type = VT1708B_4CH; | ||
122 | else if ((dev_id & 0xfff) == 0x397 | ||
123 | && (dev_id >> 12) < 8) | ||
124 | codec_type = VT1708S; | ||
125 | else if ((dev_id & 0xfff) == 0x398 | ||
126 | && (dev_id >> 12) < 8) | ||
127 | codec_type = VT1702; | ||
128 | else | ||
129 | codec_type = UNKNOWN; | ||
130 | return codec_type; | ||
131 | }; | ||
132 | |||
90 | #define VIA_HP_EVENT 0x01 | 133 | #define VIA_HP_EVENT 0x01 |
91 | #define VIA_GPIO_EVENT 0x02 | 134 | #define VIA_GPIO_EVENT 0x02 |
92 | 135 | ||
@@ -102,6 +145,48 @@ enum { | |||
102 | AUTO_SEQ_SIDE | 145 | AUTO_SEQ_SIDE |
103 | }; | 146 | }; |
104 | 147 | ||
148 | #define get_amp_nid(kc) ((kc)->private_value & 0xffff) | ||
149 | |||
150 | /* Some VT1708S based boards gets the micboost setting wrong, so we have | ||
151 | * to apply some brute-force and re-write the TLV's by software. */ | ||
152 | static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
153 | unsigned int size, unsigned int __user *_tlv) | ||
154 | { | ||
155 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
156 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
157 | |||
158 | if (get_codec_type(codec->vendor_id) == VT1708S | ||
159 | && (nid == 0x1a || nid == 0x1e)) { | ||
160 | if (size < 4 * sizeof(unsigned int)) | ||
161 | return -ENOMEM; | ||
162 | if (put_user(1, _tlv)) /* SNDRV_CTL_TLVT_DB_SCALE */ | ||
163 | return -EFAULT; | ||
164 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | ||
165 | return -EFAULT; | ||
166 | if (put_user(0, _tlv + 2)) /* offset = 0 */ | ||
167 | return -EFAULT; | ||
168 | if (put_user(1000, _tlv + 3)) /* step size = 10 dB */ | ||
169 | return -EFAULT; | ||
170 | } | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int mic_boost_volume_info(struct snd_kcontrol *kcontrol, | ||
175 | struct snd_ctl_elem_info *uinfo) | ||
176 | { | ||
177 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
178 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
179 | |||
180 | if (get_codec_type(codec->vendor_id) == VT1708S | ||
181 | && (nid == 0x1a || nid == 0x1e)) { | ||
182 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
183 | uinfo->count = 2; | ||
184 | uinfo->value.integer.min = 0; | ||
185 | uinfo->value.integer.max = 3; | ||
186 | } | ||
187 | return 0; | ||
188 | } | ||
189 | |||
105 | static struct snd_kcontrol_new vt1708_control_templates[] = { | 190 | static struct snd_kcontrol_new vt1708_control_templates[] = { |
106 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 191 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
107 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 192 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
@@ -2430,14 +2515,29 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) | |||
2430 | 2515 | ||
2431 | /* Patch for VT1708S */ | 2516 | /* Patch for VT1708S */ |
2432 | 2517 | ||
2518 | /* VT1708S software backdoor based override for buggy hardware micboost | ||
2519 | * setting */ | ||
2520 | #define MIC_BOOST_VOLUME(xname, nid) { \ | ||
2521 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2522 | .name = xname, \ | ||
2523 | .index = 0, \ | ||
2524 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
2525 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
2526 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
2527 | .info = mic_boost_volume_info, \ | ||
2528 | .get = snd_hda_mixer_amp_volume_get, \ | ||
2529 | .put = snd_hda_mixer_amp_volume_put, \ | ||
2530 | .tlv = { .c = mic_boost_tlv }, \ | ||
2531 | .private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT) } | ||
2532 | |||
2433 | /* capture mixer elements */ | 2533 | /* capture mixer elements */ |
2434 | static struct snd_kcontrol_new vt1708S_capture_mixer[] = { | 2534 | static struct snd_kcontrol_new vt1708S_capture_mixer[] = { |
2435 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), | 2535 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), |
2436 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), | 2536 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), |
2437 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), | 2537 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), |
2438 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT), | 2538 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT), |
2439 | HDA_CODEC_VOLUME("Mic Boost", 0x1A, 0x0, HDA_INPUT), | 2539 | MIC_BOOST_VOLUME("Mic Boost Capture Volume", 0x1A), |
2440 | HDA_CODEC_VOLUME("Front Mic Boost", 0x1E, 0x0, HDA_INPUT), | 2540 | MIC_BOOST_VOLUME("Front Mic Boost Capture Volume", 0x1E), |
2441 | { | 2541 | { |
2442 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2542 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2443 | /* The multiple "Capture Source" controls confuse alsamixer | 2543 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -2472,6 +2572,8 @@ static struct hda_verb vt1708S_volume_init_verbs[] = { | |||
2472 | /* PW9, PW10 Output enable */ | 2572 | /* PW9, PW10 Output enable */ |
2473 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2573 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
2474 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2574 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
2575 | /* Enable Mic Boost Volume backdoor */ | ||
2576 | {0x1, 0xf98, 0x1}, | ||
2475 | { } | 2577 | { } |
2476 | }; | 2578 | }; |
2477 | 2579 | ||