|
@@ -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,12 +1499,44 @@ 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;
|
|
@@ -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);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|