At Mon,  3 Nov 2014 21:35:48 +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 <li...@rainbow-software.org>

Thanks, applied.


Takashi

> ---
>  sound/isa/es18xx.c |   52 
> ++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 42 insertions(+), 10 deletions(-)
> 
> diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
> index 6faaac6..0ead1c8 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
> +             val = snd_es18xx_reg_read(chip, reg);
>       ucontrol->value.integer.value[0] = (val >> shift) & mask;
>       if (invert)
>               ucontrol->value.integer.value[0] = mask - 
> ucontrol->value.integer.value[0];
> @@ -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,15 @@ static int snd_es18xx_put_single(struct snd_kcontrol 
> *kcontrol, struct snd_ctl_e
>               val = mask - val;
>       mask <<= shift;
>       val <<= shift;
> +     if (pm_port) {
> +             unsigned char cur = inb(chip->port + ES18XX_PM);
> +
> +             if ((cur & mask) == val)
> +                     return 0;
> +             outb((cur & ~mask) | val, chip->port + ES18XX_PM);
> +             return 1;
> +     }
> +
>       return snd_es18xx_reg_bits(chip, reg, mask, val) != val;
>  }
>  
> @@ -1304,7 +1322,7 @@ static struct snd_kcontrol_new snd_es18xx_opt_speaker =
>       ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
>  
>  static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
> -ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
> +ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, ES18XX_FL_INVERT),
>  ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0),
>  ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
>  ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0)
> @@ -1363,6 +1381,11 @@ static struct snd_kcontrol_new 
> snd_es18xx_hw_volume_controls[] = {
>  ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
>  };
>  
> +static struct snd_kcontrol_new snd_es18xx_opt_gpo_2bit[] = {
> +ES18XX_SINGLE("GPO0 Switch", 0, ES18XX_PM, 0, 1, ES18XX_FL_PMPORT),
> +ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT),
> +};
> +
>  static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
>  {
>       int data;
> @@ -1629,10 +1652,10 @@ static int snd_es18xx_probe(struct snd_es18xx *chip,
>  
>       switch (chip->version) {
>       case 0x1868:
> -             chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | 
> ES18XX_CONTROL;
> +             chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | 
> ES18XX_CONTROL | ES18XX_GPO_2BIT;
>               break;
>       case 0x1869:
> -             chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | 
> ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL 
> | ES18XX_HWV;
> +             chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | 
> ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL 
> | ES18XX_HWV | ES18XX_GPO_2BIT;
>               break;
>       case 0x1878:
>               chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | 
> ES18XX_I2S | ES18XX_CONTROL;
> @@ -1642,7 +1665,7 @@ static int snd_es18xx_probe(struct snd_es18xx *chip,
>               break;
>       case 0x1887:
>       case 0x1888:
> -             chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | 
> ES18XX_DUPLEX_SAME;
> +             chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | 
> ES18XX_DUPLEX_SAME | ES18XX_GPO_2BIT;
>               break;
>       default:
>               snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n",
> @@ -1944,6 +1967,15 @@ static int snd_es18xx_mixer(struct snd_card *card)
>                               return err;
>               }
>       }
> +     if (chip->caps & ES18XX_GPO_2BIT) {
> +             for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_gpo_2bit); idx++) 
> {
> +                     err = snd_ctl_add(card,
> +                                       
> snd_ctl_new1(&snd_es18xx_opt_gpo_2bit[idx],
> +                                                    chip));
> +                     if (err < 0)
> +                             return err;
> +             }
> +     }
>       return 0;
>  }
>         
> -- 
> Ondrej Zary
> 
> _______________________________________________
> Alsa-devel mailing list
> alsa-de...@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to