aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorRandy Cushman <rcushman_linux@earthlink.net>2006-12-21 13:17:29 -0500
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:02:45 -0500
commit6428ea1b733e4795209ff272be32732ec152594a (patch)
tree9804697d4617ec6f63c18d9304c0c828c8ef29a2 /sound/pci
parent1321b160fa1cf63fa841d954fe31220366b6647a (diff)
[ALSA] ac97 - fix malfunctioning mixer controls for AD1985
This patch replaces the 'V_REFOUT Enable' mixer switch control with a listbox control for the AD1985 CODEC. Previous patch 'AD1888 mixer controls for DC mode' added controls that were propogated to multiple codecs. For the AD1985 codec, the bits VREFH and VREFD function differently, preventing the 'V_REFOUT Enable' control from setting V_REFOUT to Hi-Z. This patch also corrects an issue in which register bits relating to mixer controls 'Surround Jack Mode' and 'Channel Mode'. The register bits controlled by these controls were being set at boot time to states inconsistent with the stored values of these controls. Signed-off-by: Randy Cushman <rcushman_linux@earthlink.net> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/ac97/ac97_patch.c103
1 files changed, 92 insertions, 11 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 5f69b9c9f1b3..bd27531a0f0e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1632,13 +1632,16 @@ int patch_ad1886(struct snd_ac97 * ac97)
1632#define AC97_AD198X_MBC_10 0x0001 /* +10dB */ 1632#define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1633#define AC97_AD198X_MBC_30 0x0002 /* +30dB */ 1633#define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1634#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */ 1634#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1635#define AC97_AD198X_VREFH 0x0008 /* 2.25V, 3.7V */ 1635#define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1636#define AC97_AD198X_VREF_0 0x000c /* 0V */ 1636#define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */
1637#define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1638#define AC97_AD198X_VREF_SHIFT 2
1637#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */ 1639#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1638#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */ 1640#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1639#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */ 1641#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1640#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */ 1642#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1641#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: 0 = 6-to-4, 1 = 6-to-2 downmix */ 1643#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */
1644 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1642#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */ 1645#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1643#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */ 1646#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1644#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */ 1647#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
@@ -1969,8 +1972,80 @@ int patch_ad1980(struct snd_ac97 * ac97)
1969 return 0; 1972 return 0;
1970} 1973}
1971 1974
1975static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
1976 struct snd_ctl_elem_info *uinfo)
1977{
1978 static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
1979
1980 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1981 uinfo->count = 1;
1982 uinfo->value.enumerated.items = 4;
1983 if (uinfo->value.enumerated.item > 3)
1984 uinfo->value.enumerated.item = 3;
1985 strcpy(uinfo->value.enumerated.name,
1986 texts[uinfo->value.enumerated.item]);
1987 return 0;
1988}
1989
1990static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
1991 struct snd_ctl_elem_value *ucontrol)
1992{
1993 static const int reg2ctrl[4] = {2, 0, 1, 3};
1994 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
1995 unsigned short val;
1996 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
1997 >> AC97_AD198X_VREF_SHIFT;
1998 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
1999 return 0;
2000}
2001
2002static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2003 struct snd_ctl_elem_value *ucontrol)
2004{
2005 static const int ctrl2reg[4] = {1, 2, 0, 3};
2006 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2007 unsigned short val;
2008
2009 if (ucontrol->value.enumerated.item[0] > 3
2010 || ucontrol->value.enumerated.item[0] < 0)
2011 return -EINVAL;
2012 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2013 << AC97_AD198X_VREF_SHIFT;
2014 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2015 AC97_AD198X_VREF_MASK, val);
2016}
2017
1972static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = { 2018static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
1973 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) 2019 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2020 {
2021 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2022 .name = "Exchange Front/Surround",
2023 .info = snd_ac97_ad1888_lohpsel_info,
2024 .get = snd_ac97_ad1888_lohpsel_get,
2025 .put = snd_ac97_ad1888_lohpsel_put
2026 },
2027 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2028 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2029 AC97_AD_MISC, 7, 1, 0),
2030 {
2031 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2032 .name = "Downmix",
2033 .info = snd_ac97_ad1888_downmix_info,
2034 .get = snd_ac97_ad1888_downmix_get,
2035 .put = snd_ac97_ad1888_downmix_put
2036 },
2037 {
2038 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2039 .name = "V_REFOUT",
2040 .info = snd_ac97_ad1985_vrefout_info,
2041 .get = snd_ac97_ad1985_vrefout_get,
2042 .put = snd_ac97_ad1985_vrefout_put
2043 },
2044 AC97_SURROUND_JACK_MODE_CTL,
2045 AC97_CHANNEL_MODE_CTL,
2046
2047 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2048 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1974}; 2049};
1975 2050
1976static void ad1985_update_jacks(struct snd_ac97 *ac97) 2051static void ad1985_update_jacks(struct snd_ac97 *ac97)
@@ -1984,9 +2059,16 @@ static int patch_ad1985_specific(struct snd_ac97 *ac97)
1984{ 2059{
1985 int err; 2060 int err;
1986 2061
1987 if ((err = patch_ad1980_specific(ac97)) < 0) 2062 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2063 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2064 "Master Surround Playback");
2065 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2066
2067 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
1988 return err; 2068 return err;
1989 return patch_build_controls(ac97, snd_ac97_ad1985_controls, ARRAY_SIZE(snd_ac97_ad1985_controls)); 2069
2070 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2071 ARRAY_SIZE(snd_ac97_ad1985_controls));
1990} 2072}
1991 2073
1992static struct snd_ac97_build_ops patch_ad1985_build_ops = { 2074static struct snd_ac97_build_ops patch_ad1985_build_ops = {
@@ -2006,19 +2088,18 @@ int patch_ad1985(struct snd_ac97 * ac97)
2006 ac97->build_ops = &patch_ad1985_build_ops; 2088 ac97->build_ops = &patch_ad1985_build_ops;
2007 misc = snd_ac97_read(ac97, AC97_AD_MISC); 2089 misc = snd_ac97_read(ac97, AC97_AD_MISC);
2008 /* switch front/surround line-out/hp-out */ 2090 /* switch front/surround line-out/hp-out */
2009 /* center/LFE, mic in 3.75V mode */
2010 /* AD-compatible mode */ 2091 /* AD-compatible mode */
2011 /* Stereo mutes enabled */ 2092 /* Stereo mutes enabled */
2012 /* in accordance with ADI driver: misc | 0x5c28 */
2013 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 2093 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
2014 AC97_AD198X_VREFH |
2015 AC97_AD198X_LOSEL | 2094 AC97_AD198X_LOSEL |
2016 AC97_AD198X_HPSEL | 2095 AC97_AD198X_HPSEL |
2017 AC97_AD198X_CLDIS |
2018 AC97_AD198X_LODIS |
2019 AC97_AD198X_MSPLT | 2096 AC97_AD198X_MSPLT |
2020 AC97_AD198X_AC97NC); 2097 AC97_AD198X_AC97NC);
2021 ac97->flags |= AC97_STEREO_MUTES; 2098 ac97->flags |= AC97_STEREO_MUTES;
2099
2100 /* update current jack configuration */
2101 ad1985_update_jacks(ac97);
2102
2022 /* on AD1985 rev. 3, AC'97 revision bits are zero */ 2103 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2023 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23; 2104 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2024 return 0; 2105 return 0;