At Sun, 2 Nov 2014 23:18:49 +0100, Ondrej Zary wrote:
Add GPO0 and GPO1 (General Purpose Outputs) controls to mixer. These can be used on some cards to control amplifier mute (seen in ES1868 datasheet) or additional onboard chips such as QX2130 QXpander processor.
These GPOs are present on ES1868, ES1869, ES1887 and ES1888 chips.
Tested on ES1868 with QX2130.
Signed-off-by: Ondrej Zary linux@rainbow-software.org
sound/isa/es18xx.c | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 6faaac6..8966ed2 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -156,6 +156,7 @@ struct snd_es18xx { #define ES18XX_I2S 0x0200 /* I2S mixer control */ #define ES18XX_MUTEREC 0x0400 /* Record source can be muted */ #define ES18XX_CONTROL 0x0800 /* Has control ports */ +#define ES18XX_GPO_2BIT 0x1000 /* GPO0,1 controlled by PM port */
/* Power Management */ #define ES18XX_PM 0x07 @@ -1136,11 +1137,14 @@ static int snd_es18xx_reg_read(struct snd_es18xx *chip, unsigned char reg) return snd_es18xx_read(chip, reg); }
-#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \ +#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, flags) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_es18xx_info_single, \ .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \
- .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
- .private_value = reg | (shift << 8) | (mask << 16) | (flags << 24) }
+#define ES18XX_FL_INVERT (1 << 0) +#define ES18XX_FL_PMPORT (1 << 1)
static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -1159,10 +1163,14 @@ static int snd_es18xx_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
- int invert = (kcontrol->private_value >> 24) & ES18XX_FL_INVERT;
- int pm_port = (kcontrol->private_value >> 24) & ES18XX_FL_PMPORT; int val;
- val = snd_es18xx_reg_read(chip, reg);
- if (pm_port)
val = inb(chip->port + ES18XX_PM);
- else
ucontrol->value.integer.value[0] = (val >> shift) & mask; if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];val = snd_es18xx_reg_read(chip, reg);
@@ -1175,7 +1183,8 @@ static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 24) & ES18XX_FL_INVERT;
int pm_port = (kcontrol->private_value >> 24) & ES18XX_FL_PMPORT; unsigned char val;
val = (ucontrol->value.integer.value[0] & mask);
@@ -1183,6 +1192,12 @@ static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e val = mask - val; mask <<= shift; val <<= shift;
- if (pm_port) {
val = (inb(chip->port + ES18XX_PM) & ~mask) | val;
outb(val, chip->port + ES18XX_PM);
return 0;
A put callback is supposed to return 1 if the hardware is updated to the given value, or return 0 if the hardware value was same.
thanks,
Takashi