aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ac97/ac97_patch.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ac97/ac97_patch.c')
-rw-r--r--sound/pci/ac97/ac97_patch.c549
1 files changed, 507 insertions, 42 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index e813968e0cf8..641d0c8d659e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -54,7 +54,7 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro
54 54
55/* replace with a new TLV */ 55/* replace with a new TLV */
56static void reset_tlv(struct snd_ac97 *ac97, const char *name, 56static void reset_tlv(struct snd_ac97 *ac97, const char *name,
57 unsigned int *tlv) 57 const unsigned int *tlv)
58{ 58{
59 struct snd_ctl_elem_id sid; 59 struct snd_ctl_elem_id sid;
60 struct snd_kcontrol *kctl; 60 struct snd_kcontrol *kctl;
@@ -190,14 +190,28 @@ static inline int is_clfe_on(struct snd_ac97 *ac97)
190 return ac97->channel_mode >= 2; 190 return ac97->channel_mode >= 2;
191} 191}
192 192
193/* system has shared jacks with surround out enabled */
194static inline int is_shared_surrout(struct snd_ac97 *ac97)
195{
196 return !ac97->indep_surround && is_surround_on(ac97);
197}
198
199/* system has shared jacks with center/lfe out enabled */
200static inline int is_shared_clfeout(struct snd_ac97 *ac97)
201{
202 return !ac97->indep_surround && is_clfe_on(ac97);
203}
204
205/* system has shared jacks with line in enabled */
193static inline int is_shared_linein(struct snd_ac97 *ac97) 206static inline int is_shared_linein(struct snd_ac97 *ac97)
194{ 207{
195 return ! ac97->indep_surround && is_surround_on(ac97); 208 return !ac97->indep_surround && !is_surround_on(ac97);
196} 209}
197 210
211/* system has shared jacks with mic in enabled */
198static inline int is_shared_micin(struct snd_ac97 *ac97) 212static inline int is_shared_micin(struct snd_ac97 *ac97)
199{ 213{
200 return ! ac97->indep_surround && is_clfe_on(ac97); 214 return !ac97->indep_surround && !is_clfe_on(ac97);
201} 215}
202 216
203 217
@@ -941,6 +955,9 @@ static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
941{ 955{
942 int err; 956 int err;
943 957
958 /* the register bit is writable, but the function is not implemented: */
959 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
960
944 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); 961 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
945 if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) 962 if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
946 return err; 963 return err;
@@ -1552,7 +1569,7 @@ static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1552 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ 1569 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1553}; 1570};
1554 1571
1555static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0); 1572static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1556 1573
1557static int patch_ad1885_specific(struct snd_ac97 * ac97) 1574static int patch_ad1885_specific(struct snd_ac97 * ac97)
1558{ 1575{
@@ -1609,19 +1626,22 @@ int patch_ad1886(struct snd_ac97 * ac97)
1609 return 0; 1626 return 0;
1610} 1627}
1611 1628
1612/* MISC bits */ 1629/* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
1613#define AC97_AD198X_MBC 0x0003 /* mic boost */ 1630#define AC97_AD198X_MBC 0x0003 /* mic boost */
1614#define AC97_AD198X_MBC_20 0x0000 /* +20dB */ 1631#define AC97_AD198X_MBC_20 0x0000 /* +20dB */
1615#define AC97_AD198X_MBC_10 0x0001 /* +10dB */ 1632#define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1616#define AC97_AD198X_MBC_30 0x0002 /* +30dB */ 1633#define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1617#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */ 1634#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1618#define AC97_AD198X_VREFH 0x0008 /* 2.25V, 3.7V */ 1635#define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1619#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
1620#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */ 1639#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1621#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */ 1640#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1622#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */ 1641#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1623#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */ 1642#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1624#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 */
1625#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */ 1645#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1626#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */ 1646#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1627#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */ 1647#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
@@ -1630,6 +1650,83 @@ int patch_ad1886(struct snd_ac97 * ac97)
1630#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */ 1650#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
1631#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */ 1651#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
1632 1652
1653/* MISC 1 bits (AD1986 register 0x76) */
1654#define AC97_AD1986_MBC 0x0003 /* mic boost */
1655#define AC97_AD1986_MBC_20 0x0000 /* +20dB */
1656#define AC97_AD1986_MBC_10 0x0001 /* +10dB */
1657#define AC97_AD1986_MBC_30 0x0002 /* +30dB */
1658#define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */
1659#define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */
1660#define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1661#define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */
1662#define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */
1663#define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */
1664#define AC97_AD1986_SRU 0x0010 /* sample rate unlock */
1665#define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */
1666#define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */
1667#define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */
1668#define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */
1669 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1670#define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1671#define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */
1672#define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */
1673#define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */
1674#define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */
1675#define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */
1676
1677/* MISC 2 bits (AD1986 register 0x70) */
1678#define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */
1679
1680#define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */
1681#define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */
1682#define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */
1683#define AC97_AD1986_CVREF_MASK \
1684 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1685#define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */
1686#define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */
1687#define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */
1688#define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */
1689#define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */
1690#define AC97_AD1986_MVREF_MASK \
1691 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1692
1693/* MISC 3 bits (AD1986 register 0x7a) */
1694#define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */
1695
1696#define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */
1697#define AC97_AD1986_GPO 0x0008 /* General Purpose Out */
1698#define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */
1699#define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */
1700#define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */
1701#define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */
1702#define AC97_AD1986_LVREF_MASK \
1703 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1704#define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */
1705#define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */
1706#define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */
1707 /* input select Surround DACs */
1708#define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */
1709 /* select C/LFE DACs */
1710#define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */
1711
1712/* Serial Config bits (AD1986 register 0x74) (incomplete) */
1713#define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */
1714#define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */
1715#define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */
1716#define AC97_AD1986_OMS_MASK \
1717 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1718#define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */
1719#define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */
1720#define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */
1721#define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */
1722 /* are MIC sources */
1723#define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */
1724 /* are MIC sources */
1725#define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */
1726 /* are MIC sources */
1727#define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */
1728 /* are MIC sources */
1729
1633 1730
1634static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1731static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1635{ 1732{
@@ -1952,8 +2049,80 @@ int patch_ad1980(struct snd_ac97 * ac97)
1952 return 0; 2049 return 0;
1953} 2050}
1954 2051
2052static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2053 struct snd_ctl_elem_info *uinfo)
2054{
2055 static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
2056
2057 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2058 uinfo->count = 1;
2059 uinfo->value.enumerated.items = 4;
2060 if (uinfo->value.enumerated.item > 3)
2061 uinfo->value.enumerated.item = 3;
2062 strcpy(uinfo->value.enumerated.name,
2063 texts[uinfo->value.enumerated.item]);
2064 return 0;
2065}
2066
2067static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2068 struct snd_ctl_elem_value *ucontrol)
2069{
2070 static const int reg2ctrl[4] = {2, 0, 1, 3};
2071 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2072 unsigned short val;
2073 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2074 >> AC97_AD198X_VREF_SHIFT;
2075 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2076 return 0;
2077}
2078
2079static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2080 struct snd_ctl_elem_value *ucontrol)
2081{
2082 static const int ctrl2reg[4] = {1, 2, 0, 3};
2083 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2084 unsigned short val;
2085
2086 if (ucontrol->value.enumerated.item[0] > 3
2087 || ucontrol->value.enumerated.item[0] < 0)
2088 return -EINVAL;
2089 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2090 << AC97_AD198X_VREF_SHIFT;
2091 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2092 AC97_AD198X_VREF_MASK, val);
2093}
2094
1955static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = { 2095static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
1956 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) 2096 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2097 {
2098 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2099 .name = "Exchange Front/Surround",
2100 .info = snd_ac97_ad1888_lohpsel_info,
2101 .get = snd_ac97_ad1888_lohpsel_get,
2102 .put = snd_ac97_ad1888_lohpsel_put
2103 },
2104 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2105 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2106 AC97_AD_MISC, 7, 1, 0),
2107 {
2108 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2109 .name = "Downmix",
2110 .info = snd_ac97_ad1888_downmix_info,
2111 .get = snd_ac97_ad1888_downmix_get,
2112 .put = snd_ac97_ad1888_downmix_put
2113 },
2114 {
2115 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2116 .name = "V_REFOUT",
2117 .info = snd_ac97_ad1985_vrefout_info,
2118 .get = snd_ac97_ad1985_vrefout_get,
2119 .put = snd_ac97_ad1985_vrefout_put
2120 },
2121 AC97_SURROUND_JACK_MODE_CTL,
2122 AC97_CHANNEL_MODE_CTL,
2123
2124 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2125 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1957}; 2126};
1958 2127
1959static void ad1985_update_jacks(struct snd_ac97 *ac97) 2128static void ad1985_update_jacks(struct snd_ac97 *ac97)
@@ -1967,9 +2136,16 @@ static int patch_ad1985_specific(struct snd_ac97 *ac97)
1967{ 2136{
1968 int err; 2137 int err;
1969 2138
1970 if ((err = patch_ad1980_specific(ac97)) < 0) 2139 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2140 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2141 "Master Surround Playback");
2142 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2143
2144 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
1971 return err; 2145 return err;
1972 return patch_build_controls(ac97, snd_ac97_ad1985_controls, ARRAY_SIZE(snd_ac97_ad1985_controls)); 2146
2147 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2148 ARRAY_SIZE(snd_ac97_ad1985_controls));
1973} 2149}
1974 2150
1975static struct snd_ac97_build_ops patch_ad1985_build_ops = { 2151static struct snd_ac97_build_ops patch_ad1985_build_ops = {
@@ -1989,24 +2165,311 @@ int patch_ad1985(struct snd_ac97 * ac97)
1989 ac97->build_ops = &patch_ad1985_build_ops; 2165 ac97->build_ops = &patch_ad1985_build_ops;
1990 misc = snd_ac97_read(ac97, AC97_AD_MISC); 2166 misc = snd_ac97_read(ac97, AC97_AD_MISC);
1991 /* switch front/surround line-out/hp-out */ 2167 /* switch front/surround line-out/hp-out */
1992 /* center/LFE, mic in 3.75V mode */
1993 /* AD-compatible mode */ 2168 /* AD-compatible mode */
1994 /* Stereo mutes enabled */ 2169 /* Stereo mutes enabled */
1995 /* in accordance with ADI driver: misc | 0x5c28 */
1996 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 2170 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
1997 AC97_AD198X_VREFH |
1998 AC97_AD198X_LOSEL | 2171 AC97_AD198X_LOSEL |
1999 AC97_AD198X_HPSEL | 2172 AC97_AD198X_HPSEL |
2000 AC97_AD198X_CLDIS |
2001 AC97_AD198X_LODIS |
2002 AC97_AD198X_MSPLT | 2173 AC97_AD198X_MSPLT |
2003 AC97_AD198X_AC97NC); 2174 AC97_AD198X_AC97NC);
2004 ac97->flags |= AC97_STEREO_MUTES; 2175 ac97->flags |= AC97_STEREO_MUTES;
2176
2177 /* update current jack configuration */
2178 ad1985_update_jacks(ac97);
2179
2005 /* on AD1985 rev. 3, AC'97 revision bits are zero */ 2180 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2006 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23; 2181 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2007 return 0; 2182 return 0;
2008} 2183}
2009 2184
2185static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol,
2186 struct snd_ctl_elem_info *uinfo)
2187{
2188 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2189 uinfo->count = 1;
2190 uinfo->value.integer.min = 0;
2191 uinfo->value.integer.max = 1;
2192 return 0;
2193}
2194
2195static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2196 struct snd_ctl_elem_value *ucontrol)
2197{
2198 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2199 unsigned short val;
2200
2201 val = ac97->regs[AC97_AD_MISC3];
2202 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2203 return 0;
2204}
2205
2206static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2207 struct snd_ctl_elem_value *ucontrol)
2208{
2209 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2210 int ret0;
2211 int ret1;
2212 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2213
2214 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2215 ucontrol->value.integer.value[0] != 0
2216 ? AC97_AD1986_LOSEL : 0);
2217 if (ret0 < 0)
2218 return ret0;
2219
2220 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2221 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2222 (ucontrol->value.integer.value[0] != 0
2223 || sprd)
2224 ? AC97_AD1986_SOSEL : 0);
2225 if (ret1 < 0)
2226 return ret1;
2227
2228 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2229}
2230
2231static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2232 struct snd_ctl_elem_value *ucontrol)
2233{
2234 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2235 unsigned short val;
2236
2237 val = ac97->regs[AC97_AD_MISC];
2238 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2239 return 0;
2240}
2241
2242static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2243 struct snd_ctl_elem_value *ucontrol)
2244{
2245 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2246 int ret0;
2247 int ret1;
2248 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2249
2250 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2251 ucontrol->value.integer.value[0] != 0
2252 ? AC97_AD1986_SPRD : 0);
2253 if (ret0 < 0)
2254 return ret0;
2255
2256 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2257 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2258 (ucontrol->value.integer.value[0] != 0
2259 || sprd)
2260 ? AC97_AD1986_SOSEL : 0);
2261 if (ret1 < 0)
2262 return ret1;
2263
2264 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2265}
2266
2267static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2268 struct snd_ctl_elem_value *ucontrol)
2269{
2270 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2271
2272 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2273 return 0;
2274}
2275
2276static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2277 struct snd_ctl_elem_value *ucontrol)
2278{
2279 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2280 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2281
2282 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2283 ac97->spec.ad18xx.swap_mic_linein = swap;
2284 if (ac97->build_ops->update_jacks)
2285 ac97->build_ops->update_jacks(ac97);
2286 return 1;
2287 }
2288 return 0;
2289}
2290
2291static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2292 struct snd_ctl_elem_value *ucontrol)
2293{
2294 /* Use MIC_1/2 V_REFOUT as the "get" value */
2295 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2296 unsigned short val;
2297 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2298 if ((reg & AC97_AD1986_MVREF0) != 0)
2299 val = 2;
2300 else if ((reg & AC97_AD1986_MVREF1) != 0)
2301 val = 3;
2302 else if ((reg & AC97_AD1986_MVREF2) != 0)
2303 val = 1;
2304 else
2305 val = 0;
2306 ucontrol->value.enumerated.item[0] = val;
2307 return 0;
2308}
2309
2310static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2311 struct snd_ctl_elem_value *ucontrol)
2312{
2313 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2314 unsigned short cval;
2315 unsigned short lval;
2316 unsigned short mval;
2317 int cret;
2318 int lret;
2319 int mret;
2320
2321 switch (ucontrol->value.enumerated.item[0])
2322 {
2323 case 0: /* High-Z */
2324 cval = 0;
2325 lval = 0;
2326 mval = 0;
2327 break;
2328 case 1: /* 3.7 V */
2329 cval = AC97_AD1986_CVREF2;
2330 lval = AC97_AD1986_LVREF2;
2331 mval = AC97_AD1986_MVREF2;
2332 break;
2333 case 2: /* 2.25 V */
2334 cval = AC97_AD1986_CVREF0;
2335 lval = AC97_AD1986_LVREF0;
2336 mval = AC97_AD1986_MVREF0;
2337 break;
2338 case 3: /* 0 V */
2339 cval = AC97_AD1986_CVREF1;
2340 lval = AC97_AD1986_LVREF1;
2341 mval = AC97_AD1986_MVREF1;
2342 break;
2343 default:
2344 return -EINVAL;
2345 }
2346
2347 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2348 AC97_AD1986_CVREF_MASK, cval);
2349 if (cret < 0)
2350 return cret;
2351 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2352 AC97_AD1986_LVREF_MASK, lval);
2353 if (lret < 0)
2354 return lret;
2355 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2356 AC97_AD1986_MVREF_MASK, mval);
2357 if (mret < 0)
2358 return mret;
2359
2360 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2361}
2362
2363static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2364 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2365 {
2366 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2367 .name = "Exchange Front/Surround",
2368 .info = snd_ac97_ad1986_bool_info,
2369 .get = snd_ac97_ad1986_lososel_get,
2370 .put = snd_ac97_ad1986_lososel_put
2371 },
2372 {
2373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2374 .name = "Exchange Mic/Line In",
2375 .info = snd_ac97_ad1986_bool_info,
2376 .get = snd_ac97_ad1986_miclisel_get,
2377 .put = snd_ac97_ad1986_miclisel_put
2378 },
2379 {
2380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2381 .name = "Spread Front to Surround and Center/LFE",
2382 .info = snd_ac97_ad1986_bool_info,
2383 .get = snd_ac97_ad1986_spread_get,
2384 .put = snd_ac97_ad1986_spread_put
2385 },
2386 {
2387 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2388 .name = "Downmix",
2389 .info = snd_ac97_ad1888_downmix_info,
2390 .get = snd_ac97_ad1888_downmix_get,
2391 .put = snd_ac97_ad1888_downmix_put
2392 },
2393 {
2394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2395 .name = "V_REFOUT",
2396 .info = snd_ac97_ad1985_vrefout_info,
2397 .get = snd_ac97_ad1986_vrefout_get,
2398 .put = snd_ac97_ad1986_vrefout_put
2399 },
2400 AC97_SURROUND_JACK_MODE_CTL,
2401 AC97_CHANNEL_MODE_CTL,
2402
2403 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2404 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2405};
2406
2407static void ad1986_update_jacks(struct snd_ac97 *ac97)
2408{
2409 unsigned short misc_val = 0;
2410 unsigned short ser_val;
2411
2412 /* disable SURROUND and CENTER/LFE if not surround mode */
2413 if (! is_surround_on(ac97))
2414 misc_val |= AC97_AD1986_SODIS;
2415 if (! is_clfe_on(ac97))
2416 misc_val |= AC97_AD1986_CLDIS;
2417
2418 /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
2419 if (is_shared_linein(ac97))
2420 misc_val |= AC97_AD1986_LISEL_SURR;
2421 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2422 misc_val |= AC97_AD1986_LISEL_MIC;
2423 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2424 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2425 AC97_AD1986_LISEL_MASK,
2426 misc_val);
2427
2428 /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
2429 if (is_shared_micin(ac97))
2430 ser_val = AC97_AD1986_OMS_C;
2431 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2432 ser_val = AC97_AD1986_OMS_L;
2433 else
2434 ser_val = AC97_AD1986_OMS_M;
2435 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2436 AC97_AD1986_OMS_MASK,
2437 ser_val);
2438}
2439
2440static int patch_ad1986_specific(struct snd_ac97 *ac97)
2441{
2442 int err;
2443
2444 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2445 return err;
2446
2447 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2448 ARRAY_SIZE(snd_ac97_ad1985_controls));
2449}
2450
2451static struct snd_ac97_build_ops patch_ad1986_build_ops = {
2452 .build_post_spdif = patch_ad198x_post_spdif,
2453 .build_specific = patch_ad1986_specific,
2454#ifdef CONFIG_PM
2455 .resume = ad18xx_resume,
2456#endif
2457 .update_jacks = ad1986_update_jacks,
2458};
2459
2460int patch_ad1986(struct snd_ac97 * ac97)
2461{
2462 patch_ad1881(ac97);
2463 ac97->build_ops = &patch_ad1986_build_ops;
2464 ac97->flags |= AC97_STEREO_MUTES;
2465
2466 /* update current jack configuration */
2467 ad1986_update_jacks(ac97);
2468
2469 return 0;
2470}
2471
2472
2010/* 2473/*
2011 * realtek ALC65x/850 codecs 2474 * realtek ALC65x/850 codecs
2012 */ 2475 */
@@ -2014,12 +2477,12 @@ static void alc650_update_jacks(struct snd_ac97 *ac97)
2014{ 2477{
2015 int shared; 2478 int shared;
2016 2479
2017 /* shared Line-In */ 2480 /* shared Line-In / Surround Out */
2018 shared = is_shared_linein(ac97); 2481 shared = is_shared_surrout(ac97);
2019 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, 2482 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2020 shared ? (1 << 9) : 0); 2483 shared ? (1 << 9) : 0);
2021 /* update shared Mic */ 2484 /* update shared Mic In / Center/LFE Out */
2022 shared = is_shared_micin(ac97); 2485 shared = is_shared_clfeout(ac97);
2023 /* disable/enable vref */ 2486 /* disable/enable vref */
2024 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, 2487 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2025 shared ? (1 << 12) : 0); 2488 shared ? (1 << 12) : 0);
@@ -2064,7 +2527,7 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2064 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ 2527 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2065}; 2528};
2066 2529
2067static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0); 2530static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2068 2531
2069static int patch_alc650_specific(struct snd_ac97 * ac97) 2532static int patch_alc650_specific(struct snd_ac97 * ac97)
2070{ 2533{
@@ -2149,12 +2612,12 @@ static void alc655_update_jacks(struct snd_ac97 *ac97)
2149{ 2612{
2150 int shared; 2613 int shared;
2151 2614
2152 /* shared Line-In */ 2615 /* shared Line-In / Surround Out */
2153 shared = is_shared_linein(ac97); 2616 shared = is_shared_surrout(ac97);
2154 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, 2617 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2155 shared ? (1 << 9) : 0, 0); 2618 shared ? (1 << 9) : 0, 0);
2156 /* update shared mic */ 2619 /* update shared Mic In / Center/LFE Out */
2157 shared = is_shared_micin(ac97); 2620 shared = is_shared_clfeout(ac97);
2158 /* misc control; vrefout disable */ 2621 /* misc control; vrefout disable */
2159 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, 2622 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2160 shared ? (1 << 12) : 0); 2623 shared ? (1 << 12) : 0);
@@ -2264,7 +2727,8 @@ int patch_alc655(struct snd_ac97 * ac97)
2264 if (ac97->subsystem_vendor == 0x1462 && 2727 if (ac97->subsystem_vendor == 0x1462 &&
2265 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ 2728 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
2266 ac97->subsystem_device == 0x0161 || /* LG K1 Express */ 2729 ac97->subsystem_device == 0x0161 || /* LG K1 Express */
2267 ac97->subsystem_device == 0x0351)) /* MSI L725 laptop */ 2730 ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
2731 ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */
2268 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ 2732 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
2269 else 2733 else
2270 val |= (1 << 1); /* Pin 47 is spdif input pin */ 2734 val |= (1 << 1); /* Pin 47 is spdif input pin */
@@ -2297,16 +2761,16 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
2297{ 2761{
2298 int shared; 2762 int shared;
2299 2763
2300 /* shared Line-In */ 2764 /* shared Line-In / Surround Out */
2301 shared = is_shared_linein(ac97); 2765 shared = is_shared_surrout(ac97);
2302 /* SURR 1kOhm (bit4), Amp (bit5) */ 2766 /* SURR 1kOhm (bit4), Amp (bit5) */
2303 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), 2767 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2304 shared ? (1<<5) : (1<<4)); 2768 shared ? (1<<5) : (1<<4));
2305 /* LINE-IN = 0, SURROUND = 2 */ 2769 /* LINE-IN = 0, SURROUND = 2 */
2306 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, 2770 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2307 shared ? (2<<12) : (0<<12)); 2771 shared ? (2<<12) : (0<<12));
2308 /* update shared mic */ 2772 /* update shared Mic In / Center/LFE Out */
2309 shared = is_shared_micin(ac97); 2773 shared = is_shared_clfeout(ac97);
2310 /* Vref disable (bit12), 1kOhm (bit13) */ 2774 /* Vref disable (bit12), 1kOhm (bit13) */
2311 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), 2775 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2312 shared ? (1<<12) : (1<<13)); 2776 shared ? (1<<12) : (1<<13));
@@ -2379,9 +2843,9 @@ int patch_alc850(struct snd_ac97 *ac97)
2379 */ 2843 */
2380static void cm9738_update_jacks(struct snd_ac97 *ac97) 2844static void cm9738_update_jacks(struct snd_ac97 *ac97)
2381{ 2845{
2382 /* shared Line-In */ 2846 /* shared Line-In / Surround Out */
2383 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, 2847 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2384 is_shared_linein(ac97) ? (1 << 10) : 0); 2848 is_shared_surrout(ac97) ? (1 << 10) : 0);
2385} 2849}
2386 2850
2387static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = { 2851static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
@@ -2463,12 +2927,12 @@ static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
2463 2927
2464static void cm9739_update_jacks(struct snd_ac97 *ac97) 2928static void cm9739_update_jacks(struct snd_ac97 *ac97)
2465{ 2929{
2466 /* shared Line-In */ 2930 /* shared Line-In / Surround Out */
2467 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, 2931 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
2468 is_shared_linein(ac97) ? (1 << 10) : 0); 2932 is_shared_surrout(ac97) ? (1 << 10) : 0);
2469 /* shared Mic */ 2933 /* shared Mic In / Center/LFE Out **/
2470 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, 2934 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
2471 is_shared_micin(ac97) ? 0x1000 : 0x2000); 2935 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
2472} 2936}
2473 2937
2474static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = { 2938static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
@@ -2580,8 +3044,8 @@ static void cm9761_update_jacks(struct snd_ac97 *ac97)
2580 3044
2581 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)]; 3045 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
2582 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)]; 3046 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
2583 val |= surr_shared[ac97->spec.dev_flags][is_shared_linein(ac97)]; 3047 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
2584 val |= clfe_shared[ac97->spec.dev_flags][is_shared_micin(ac97)]; 3048 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
2585 3049
2586 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val); 3050 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
2587} 3051}
@@ -2821,6 +3285,7 @@ int patch_vt1617a(struct snd_ac97 * ac97)
2821 snd_ac97_write_cache(ac97, 0x5c, 0x20); 3285 snd_ac97_write_cache(ac97, 0x5c, 0x20);
2822 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ 3286 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
2823 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; 3287 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3288 ac97->build_ops = &patch_vt1616_ops;
2824 return 0; 3289 return 0;
2825} 3290}
2826 3291
@@ -2828,12 +3293,12 @@ int patch_vt1617a(struct snd_ac97 * ac97)
2828 */ 3293 */
2829static void it2646_update_jacks(struct snd_ac97 *ac97) 3294static void it2646_update_jacks(struct snd_ac97 *ac97)
2830{ 3295{
2831 /* shared Line-In */ 3296 /* shared Line-In / Surround Out */
2832 snd_ac97_update_bits(ac97, 0x76, 1 << 9, 3297 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
2833 is_shared_linein(ac97) ? (1<<9) : 0); 3298 is_shared_surrout(ac97) ? (1<<9) : 0);
2834 /* shared Mic */ 3299 /* shared Mic / Center/LFE Out */
2835 snd_ac97_update_bits(ac97, 0x76, 1 << 10, 3300 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
2836 is_shared_micin(ac97) ? (1<<10) : 0); 3301 is_shared_clfeout(ac97) ? (1<<10) : 0);
2837} 3302}
2838 3303
2839static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = { 3304static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {