[ALSA] Enable DXS controls for VIA VT82xx
Honza Maly [Fri, 14 Oct 2005 16:18:01 +0000 (18:18 +0200)]
Modules: VIA82xx driver

The patch enable separate DXS controls of sound function of VIA VT82xx
controller in case DXS volume is not needed for PCM Playback volume
control emulation.

Signed-off-by: Honza Maly <hkmaly@matfyz.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

sound/pci/via82xx.c

index 78a5dfb..7d46bee 100644 (file)
@@ -361,7 +361,8 @@ struct _snd_via82xx {
        unsigned int mpu_port_saved;
 #endif
 
-       unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */
+       unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
+       unsigned char playback_volume_c[2]; /* for VIA8233/C/8235; default = 0 */
 
        unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
 
@@ -937,8 +938,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
        snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
        snd_via82xx_channel_reset(chip, viadev);
        snd_via82xx_set_table_ptr(chip, viadev);
-       outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
-       outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
+       outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
+       outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
        outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */
             (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */
             rbits | /* rate */
@@ -1498,14 +1499,46 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        via82xx_t *chip = snd_kcontrol_chip(kcontrol);
-       ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0];
-       ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1];
+       unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+
+       ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0];
+       ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];
+       return 0;
+}
+
+static int snd_via8233_pcmdxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0];
+       ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1];
        return 0;
 }
 
 static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+       unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+       unsigned long port = chip->port + 0x10 * idx;
+       unsigned char val;
+       int i, change = 0;
+
+       for (i = 0; i < 2; i++) {
+               val = ucontrol->value.integer.value[i];
+               if (val > VIA_DXS_MAX_VOLUME)
+                       val = VIA_DXS_MAX_VOLUME;
+               val = VIA_DXS_MAX_VOLUME - val;
+               change |= val != chip->playback_volume[idx][i];
+               if (change) {
+                       chip->playback_volume[idx][i] = val;
+                       outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+               }
+       }
+       return change;
+}
+
+static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       via82xx_t *chip = snd_kcontrol_chip(kcontrol);
        unsigned int idx;
        unsigned char val;
        int i, change = 0;
@@ -1515,11 +1548,12 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
                if (val > VIA_DXS_MAX_VOLUME)
                        val = VIA_DXS_MAX_VOLUME;
                val = VIA_DXS_MAX_VOLUME - val;
-               if (val != chip->playback_volume[i]) {
+               if (val != chip->playback_volume_c[i]) {
                        change = 1;
-                       chip->playback_volume[i] = val;
+                       chip->playback_volume_c[i] = val;
                        for (idx = 0; idx < 4; idx++) {
                                unsigned long port = chip->port + 0x10 * idx;
+                               chip->playback_volume[idx][i] = val;
                                outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
                        }
                }
@@ -1527,10 +1561,19 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
        return change;
 }
 
-static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
+static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = {
        .name = "PCM Playback Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_via8233_dxs_volume_info,
+       .get = snd_via8233_pcmdxs_volume_get,
+       .put = snd_via8233_pcmdxs_volume_put,
+};
+
+static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
+       .name = "VIA DXS Playback Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .count = 4,
+       .info = snd_via8233_dxs_volume_info,
        .get = snd_via8233_dxs_volume_get,
        .put = snd_via8233_dxs_volume_put,
 };
@@ -1723,12 +1766,19 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip)
                strcpy(sid.name, "PCM Playback Volume");
                sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
                if (! snd_ctl_find_id(chip->card, &sid)) {
+                       snd_printd(KERN_INFO "Using DXS as PCM Playback\n");
+                       err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip));
+                       if (err < 0)
+                               return err;
+               }
+               else /* Using DXS when PCM emulation is enabled is really weird */
+               {
+                       /* Standalone DXS controls */
                        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
                        if (err < 0)
                                return err;
                }
        }
-
        /* select spdif data slot 10/11 */
        pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
        val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;
@@ -1941,8 +1991,10 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
                int i, idx;
                for (idx = 0; idx < 4; idx++) {
                        unsigned long port = chip->port + 0x10 * idx;
-                       for (i = 0; i < 2; i++)
-                               outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+                       for (i = 0; i < 2; i++) {
+                               chip->playback_volume[idx][i]=chip->playback_volume_c[i];
+                               outb(chip->playback_volume_c[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+                       }
                }
        }