return change;
 }
 
+static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       unsigned int mask = AK_GET_MASK(kcontrol->private_value);
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = mask;
+       return 0;
+}
+
+static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+       int chip = AK_GET_CHIP(kcontrol->private_value);
+       int addr = AK_GET_ADDR(kcontrol->private_value);
+       int invert = AK_GET_INVERT(kcontrol->private_value);
+       unsigned int mask = AK_GET_MASK(kcontrol->private_value);
+       unsigned char val = snd_akm4xxx_get(ak, chip, addr);
+       
+       ucontrol->value.integer.value[0] = invert ? mask - val : val;
+
+       val = snd_akm4xxx_get(ak, chip, addr+1);
+       ucontrol->value.integer.value[1] = invert ? mask - val : val;
+
+       return 0;
+}
+
+static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+       int chip = AK_GET_CHIP(kcontrol->private_value);
+       int addr = AK_GET_ADDR(kcontrol->private_value);
+       int invert = AK_GET_INVERT(kcontrol->private_value);
+       unsigned int mask = AK_GET_MASK(kcontrol->private_value);
+       unsigned char nval = ucontrol->value.integer.value[0] % (mask+1);
+       int change0, change1;
+
+       if (invert)
+               nval = mask - nval;
+       change0 = snd_akm4xxx_get(ak, chip, addr) != nval;
+       if (change0)
+               snd_akm4xxx_write(ak, chip, addr, nval);
+
+       nval = ucontrol->value.integer.value[1] % (mask+1);
+       if (invert)
+               nval = mask - nval;
+       change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval;
+       if (change1)
+               snd_akm4xxx_write(ak, chip, addr+1, nval);
+
+
+       return change0 || change1;
+}
+
 static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_info *uinfo)
 {
        unsigned int idx, num_emphs;
        struct snd_kcontrol *ctl;
        int err;
+       int mixer_ch = 0;
+       int num_stereo;
 
        ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
        if (! ctl)
                return -ENOMEM;
 
-       for (idx = 0; idx < ak->num_dacs; ++idx) {
+       for (idx = 0; idx < ak->num_dacs; ) {
                memset(ctl, 0, sizeof(*ctl));
-               strcpy(ctl->id.name, "DAC Volume");
-               ctl->id.index = idx + ak->idx_offset * 2;
+               if (ak->channel_names == NULL) {
+                       strcpy(ctl->id.name, "DAC Volume");
+                       num_stereo = 1;
+                       ctl->id.index = mixer_ch + ak->idx_offset * 2;
+               } else {
+                       strcpy(ctl->id.name, ak->channel_names[mixer_ch]);
+                       num_stereo = ak->num_stereo[mixer_ch];
+                       ctl->id.index = 0; //mixer_ch + ak->idx_offset * 2;
+               }
                ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
                ctl->count = 1;
-               ctl->info = snd_akm4xxx_volume_info;
-               ctl->get = snd_akm4xxx_volume_get;
-               ctl->put = snd_akm4xxx_volume_put;
+               if (num_stereo == 2) {
+                       ctl->info = snd_akm4xxx_stereo_volume_info;
+                       ctl->get = snd_akm4xxx_stereo_volume_get;
+                       ctl->put = snd_akm4xxx_stereo_volume_put;
+               } else {
+                       ctl->info = snd_akm4xxx_volume_info;
+                       ctl->get = snd_akm4xxx_volume_get;
+                       ctl->put = snd_akm4xxx_volume_put;
+               }
                switch (ak->type) {
                case SND_AK4524:
                        ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
                        err = -EINVAL;
                        goto __error;
                }
+
                ctl->private_data = ak;
                if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
                        goto __error;
+
+               idx += num_stereo;
+               mixer_ch++;
        }
        for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
                memset(ctl, 0, sizeof(*ctl));
 
  * initialize the chips on M-Audio Revolution cards
  */
 
+static unsigned int revo71_num_stereo_front[] = {2};
+static char *revo71_channel_names_front[] = {"PCM Playback Volume"};
+
+static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2};
+static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume",
+                                               "PCM Side Playback Volume", "PCM Rear Playback Volume"};
+
+static unsigned int revo51_num_stereo[] = {2, 1, 1, 2};
+static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume",
+                                       "PCM LFE Playback Volume", "PCM Rear Playback Volume"};
+
 static struct snd_akm4xxx akm_revo_front __devinitdata = {
        .type = SND_AK4381,
        .num_dacs = 2,
        .ops = {
                .set_rate_val = revo_set_rate_val
-       }
+       },
+       .num_stereo = revo71_num_stereo_front,
+       .channel_names = revo71_channel_names_front
 };
 
 static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
        .num_dacs = 6,
        .ops = {
                .set_rate_val = revo_set_rate_val
-       }
+       },
+       .num_stereo = revo71_num_stereo_surround,
+       .channel_names = revo71_channel_names_surround
 };
 
 static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
        .num_dacs = 6,
        .ops = {
                .set_rate_val = revo_set_rate_val
-       }
+       },
+       .num_stereo = revo51_num_stereo,
+       .channel_names = revo51_channel_names
 };
 
 static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {