diff options
-rw-r--r-- | sound/isa/es18xx.c | 52 |
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 | ||
1129 | static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1133 | static 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 | ||
1290 | static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { | 1308 | static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { |
1291 | ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), | 1309 | ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, ES18XX_FL_INVERT), |
1292 | ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0), | 1310 | ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0), |
1293 | ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), | 1311 | ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), |
1294 | ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) | 1312 | ES18XX_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[] = { | |||
1347 | ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0), | 1365 | ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0), |
1348 | }; | 1366 | }; |
1349 | 1367 | ||
1368 | static struct snd_kcontrol_new snd_es18xx_opt_gpo_2bit[] = { | ||
1369 | ES18XX_SINGLE("GPO0 Switch", 0, ES18XX_PM, 0, 1, ES18XX_FL_PMPORT), | ||
1370 | ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT), | ||
1371 | }; | ||
1372 | |||
1350 | static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) | 1373 | static 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 | ||