Commit d7426329 authored by Harald Welte's avatar Harald Welte Committed by Jaroslav Kysela

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: default avatarLogan Li <LoganLi@viatech.com.cn>
Signed-off-by: default avatarHarald Welte <HaraldWelte@viatech.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 5691ec7f
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
/* 2008-04-09 Lydia Wang Add Independent HP feature */ /* 2008-04-09 Lydia Wang Add Independent HP feature */
/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */ /* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
/* */ /* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
...@@ -87,6 +88,48 @@ ...@@ -87,6 +88,48 @@
#define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397) #define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397)
#define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398) #define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398)
enum VIA_HDA_CODEC {
UNKNOWN = -1,
VT1708,
VT1709_10CH,
VT1709_6CH,
VT1708B_8CH,
VT1708B_4CH,
VT1708S,
VT1702,
CODEC_TYPES,
};
static enum VIA_HDA_CODEC get_codec_type(u32 vendor_id)
{
u16 ven_id = vendor_id >> 16;
u16 dev_id = vendor_id & 0xffff;
enum VIA_HDA_CODEC codec_type;
/* get codec type */
if (ven_id != 0x1106)
codec_type = UNKNOWN;
else if (dev_id >= 0x1708 && dev_id <= 0x170b)
codec_type = VT1708;
else if (dev_id >= 0xe710 && dev_id <= 0xe713)
codec_type = VT1709_10CH;
else if (dev_id >= 0xe714 && dev_id <= 0xe717)
codec_type = VT1709_6CH;
else if (dev_id >= 0xe720 && dev_id <= 0xe723)
codec_type = VT1708B_8CH;
else if (dev_id >= 0xe724 && dev_id <= 0xe727)
codec_type = VT1708B_4CH;
else if ((dev_id & 0xfff) == 0x397
&& (dev_id >> 12) < 8)
codec_type = VT1708S;
else if ((dev_id & 0xfff) == 0x398
&& (dev_id >> 12) < 8)
codec_type = VT1702;
else
codec_type = UNKNOWN;
return codec_type;
};
#define VIA_HP_EVENT 0x01 #define VIA_HP_EVENT 0x01
#define VIA_GPIO_EVENT 0x02 #define VIA_GPIO_EVENT 0x02
...@@ -102,6 +145,48 @@ enum { ...@@ -102,6 +145,48 @@ enum {
AUTO_SEQ_SIDE AUTO_SEQ_SIDE
}; };
#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
/* Some VT1708S based boards gets the micboost setting wrong, so we have
* to apply some brute-force and re-write the TLV's by software. */
static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
if (get_codec_type(codec->vendor_id) == VT1708S
&& (nid == 0x1a || nid == 0x1e)) {
if (size < 4 * sizeof(unsigned int))
return -ENOMEM;
if (put_user(1, _tlv)) /* SNDRV_CTL_TLVT_DB_SCALE */
return -EFAULT;
if (put_user(2 * sizeof(unsigned int), _tlv + 1))
return -EFAULT;
if (put_user(0, _tlv + 2)) /* offset = 0 */
return -EFAULT;
if (put_user(1000, _tlv + 3)) /* step size = 10 dB */
return -EFAULT;
}
return 0;
}
static int mic_boost_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
if (get_codec_type(codec->vendor_id) == VT1708S
&& (nid == 0x1a || nid == 0x1e)) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 3;
}
return 0;
}
static struct snd_kcontrol_new vt1708_control_templates[] = { static struct snd_kcontrol_new vt1708_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0),
...@@ -2430,14 +2515,29 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) ...@@ -2430,14 +2515,29 @@ static int patch_vt1708B_4ch(struct hda_codec *codec)
/* Patch for VT1708S */ /* Patch for VT1708S */
/* VT1708S software backdoor based override for buggy hardware micboost
* setting */
#define MIC_BOOST_VOLUME(xname, nid) { \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = 0, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
.info = mic_boost_volume_info, \
.get = snd_hda_mixer_amp_volume_get, \
.put = snd_hda_mixer_amp_volume_put, \
.tlv = { .c = mic_boost_tlv }, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT) }
/* capture mixer elements */ /* capture mixer elements */
static struct snd_kcontrol_new vt1708S_capture_mixer[] = { static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x1A, 0x0, HDA_INPUT), MIC_BOOST_VOLUME("Mic Boost Capture Volume", 0x1A),
HDA_CODEC_VOLUME("Front Mic Boost", 0x1E, 0x0, HDA_INPUT), MIC_BOOST_VOLUME("Front Mic Boost Capture Volume", 0x1E),
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* The multiple "Capture Source" controls confuse alsamixer /* The multiple "Capture Source" controls confuse alsamixer
...@@ -2472,6 +2572,8 @@ static struct hda_verb vt1708S_volume_init_verbs[] = { ...@@ -2472,6 +2572,8 @@ static struct hda_verb vt1708S_volume_init_verbs[] = {
/* PW9, PW10 Output enable */ /* PW9, PW10 Output enable */
{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* Enable Mic Boost Volume backdoor */
{0x1, 0xf98, 0x1},
{ } { }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment