aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
authorHarald Welte <HaraldWelte@viatech.com>2008-09-15 10:43:23 -0400
committerJaroslav Kysela <perex@perex.cz>2008-09-23 02:18:15 -0400
commitd74263296658f55ecca1f0b95c106b73d239ea2f (patch)
treeb84519cb5a2d163655dbfa2e2074facdd81f41de /sound/pci/hda/patch_via.c
parent5691ec7fc302ecffddfa21b19477aaaa4386d002 (diff)
ALSA: HDA VIA: Replace buggy Mic Boost
VT1708S' Mic Boost should be hidden in hardware design according to some customers' requirements. However, in case of bugs, it has to be exhibited to normal users, so we need to: * open a software backdoor, which is disabled by default in hardware * re-write .tlv & .info, to indicate the actual necessary info, which we cannot get from amplifier's capabiliies Signed-off-by: Logan Li <LoganLi@viatech.com.cn> Signed-off-by: Harald Welte <HaraldWelte@viatech.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c106
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
91enum 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
103static 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. */
152static 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
174static 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
105static struct snd_kcontrol_new vt1708_control_templates[] = { 190static 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 */
2434static struct snd_kcontrol_new vt1708S_capture_mixer[] = { 2534static 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