aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/es18xx.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 63e7323e218f..b481bb8c31bc 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -156,6 +156,7 @@ struct snd_es18xx {
156#define ES18XX_I2S 0x0200 /* I2S mixer control */ 156#define ES18XX_I2S 0x0200 /* I2S mixer control */
157#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */ 157#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */
158#define ES18XX_CONTROL 0x0800 /* Has control ports */ 158#define ES18XX_CONTROL 0x0800 /* Has control ports */
159#define ES18XX_GPO_2BIT 0x1000 /* GPO0,1 controlled by PM port */
159 160
160/* Power Management */ 161/* Power Management */
161#define ES18XX_PM 0x07 162#define ES18XX_PM 0x07
@@ -1120,11 +1121,14 @@ static int snd_es18xx_reg_read(struct snd_es18xx *chip, unsigned char reg)
1120 return snd_es18xx_read(chip, reg); 1121 return snd_es18xx_read(chip, reg);
1121} 1122}
1122 1123
1123#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \ 1124#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, flags) \
1124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 1125{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1125 .info = snd_es18xx_info_single, \ 1126 .info = snd_es18xx_info_single, \
1126 .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \ 1127 .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \
1127 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 1128 .private_value = reg | (shift << 8) | (mask << 16) | (flags << 24) }
1129
1130#define ES18XX_FL_INVERT (1 << 0)
1131#define ES18XX_FL_PMPORT (1 << 1)
1128 1132
1129static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1133static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130{ 1134{
@@ -1143,10 +1147,14 @@ static int snd_es18xx_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e
1143 int reg = kcontrol->private_value & 0xff; 1147 int reg = kcontrol->private_value & 0xff;
1144 int shift = (kcontrol->private_value >> 8) & 0xff; 1148 int shift = (kcontrol->private_value >> 8) & 0xff;
1145 int mask = (kcontrol->private_value >> 16) & 0xff; 1149 int mask = (kcontrol->private_value >> 16) & 0xff;
1146 int invert = (kcontrol->private_value >> 24) & 0xff; 1150 int invert = (kcontrol->private_value >> 24) & ES18XX_FL_INVERT;
1151 int pm_port = (kcontrol->private_value >> 24) & ES18XX_FL_PMPORT;
1147 int val; 1152 int val;
1148 1153
1149 val = snd_es18xx_reg_read(chip, reg); 1154 if (pm_port)
1155 val = inb(chip->port + ES18XX_PM);
1156 else
1157 val = snd_es18xx_reg_read(chip, reg);
1150 ucontrol->value.integer.value[0] = (val >> shift) & mask; 1158 ucontrol->value.integer.value[0] = (val >> shift) & mask;
1151 if (invert) 1159 if (invert)
1152 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; 1160 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
@@ -1159,7 +1167,8 @@ static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e
1159 int reg = kcontrol->private_value & 0xff; 1167 int reg = kcontrol->private_value & 0xff;
1160 int shift = (kcontrol->private_value >> 8) & 0xff; 1168 int shift = (kcontrol->private_value >> 8) & 0xff;
1161 int mask = (kcontrol->private_value >> 16) & 0xff; 1169 int mask = (kcontrol->private_value >> 16) & 0xff;
1162 int invert = (kcontrol->private_value >> 24) & 0xff; 1170 int invert = (kcontrol->private_value >> 24) & ES18XX_FL_INVERT;
1171 int pm_port = (kcontrol->private_value >> 24) & ES18XX_FL_PMPORT;
1163 unsigned char val; 1172 unsigned char val;
1164 1173
1165 val = (ucontrol->value.integer.value[0] & mask); 1174 val = (ucontrol->value.integer.value[0] & mask);
@@ -1167,6 +1176,15 @@ static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e
1167 val = mask - val; 1176 val = mask - val;
1168 mask <<= shift; 1177 mask <<= shift;
1169 val <<= shift; 1178 val <<= shift;
1179 if (pm_port) {
1180 unsigned char cur = inb(chip->port + ES18XX_PM);
1181
1182 if ((cur & mask) == val)
1183 return 0;
1184 outb((cur & ~mask) | val, chip->port + ES18XX_PM);
1185 return 1;
1186 }
1187
1170 return snd_es18xx_reg_bits(chip, reg, mask, val) != val; 1188 return snd_es18xx_reg_bits(chip, reg, mask, val) != val;
1171} 1189}
1172 1190
@@ -1288,7 +1306,7 @@ static struct snd_kcontrol_new snd_es18xx_opt_speaker =
1288 ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0); 1306 ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
1289 1307
1290static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { 1308static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
1291ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), 1309ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, ES18XX_FL_INVERT),
1292ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0), 1310ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0),
1293ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), 1311ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
1294ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) 1312ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0)
@@ -1347,6 +1365,11 @@ static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
1347ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0), 1365ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
1348}; 1366};
1349 1367
1368static struct snd_kcontrol_new snd_es18xx_opt_gpo_2bit[] = {
1369ES18XX_SINGLE("GPO0 Switch", 0, ES18XX_PM, 0, 1, ES18XX_FL_PMPORT),
1370ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT),
1371};
1372
1350static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) 1373static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
1351{ 1374{
1352 int data; 1375 int data;
@@ -1613,10 +1636,10 @@ static int snd_es18xx_probe(struct snd_es18xx *chip,
1613 1636
1614 switch (chip->version) { 1637 switch (chip->version) {
1615 case 0x1868: 1638 case 0x1868:
1616 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL; 1639 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL | ES18XX_GPO_2BIT;
1617 break; 1640 break;
1618 case 0x1869: 1641 case 0x1869:
1619 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV; 1642 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV | ES18XX_GPO_2BIT;
1620 break; 1643 break;
1621 case 0x1878: 1644 case 0x1878:
1622 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL; 1645 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL;
@@ -1626,7 +1649,7 @@ static int snd_es18xx_probe(struct snd_es18xx *chip,
1626 break; 1649 break;
1627 case 0x1887: 1650 case 0x1887:
1628 case 0x1888: 1651 case 0x1888:
1629 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME; 1652 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_GPO_2BIT;
1630 break; 1653 break;
1631 default: 1654 default:
1632 snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n", 1655 snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n",
@@ -1928,6 +1951,15 @@ static int snd_es18xx_mixer(struct snd_card *card)
1928 return err; 1951 return err;
1929 } 1952 }
1930 } 1953 }
1954 if (chip->caps & ES18XX_GPO_2BIT) {
1955 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_gpo_2bit); idx++) {
1956 err = snd_ctl_add(card,
1957 snd_ctl_new1(&snd_es18xx_opt_gpo_2bit[idx],
1958 chip));
1959 if (err < 0)
1960 return err;
1961 }
1962 }
1931 return 0; 1963 return 0;
1932} 1964}
1933 1965