aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/via82xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/via82xx.c')
-rw-r--r--sound/pci/via82xx.c74
1 files changed, 63 insertions, 11 deletions
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 78a5dfb66796..7d46bee828c7 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -361,7 +361,8 @@ struct _snd_via82xx {
361 unsigned int mpu_port_saved; 361 unsigned int mpu_port_saved;
362#endif 362#endif
363 363
364 unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */ 364 unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
365 unsigned char playback_volume_c[2]; /* for VIA8233/C/8235; default = 0 */
365 366
366 unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ 367 unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
367 368
@@ -937,8 +938,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
937 snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); 938 snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
938 snd_via82xx_channel_reset(chip, viadev); 939 snd_via82xx_channel_reset(chip, viadev);
939 snd_via82xx_set_table_ptr(chip, viadev); 940 snd_via82xx_set_table_ptr(chip, viadev);
940 outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); 941 outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
941 outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); 942 outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
942 outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ 943 outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */
943 (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ 944 (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */
944 rbits | /* rate */ 945 rbits | /* rate */
@@ -1498,14 +1499,46 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
1498static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1499static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1499{ 1500{
1500 via82xx_t *chip = snd_kcontrol_chip(kcontrol); 1501 via82xx_t *chip = snd_kcontrol_chip(kcontrol);
1501 ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0]; 1502 unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
1502 ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1]; 1503
1504 ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0];
1505 ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];
1506 return 0;
1507}
1508
1509static int snd_via8233_pcmdxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1510{
1511 via82xx_t *chip = snd_kcontrol_chip(kcontrol);
1512 ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0];
1513 ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1];
1503 return 0; 1514 return 0;
1504} 1515}
1505 1516
1506static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 1517static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1507{ 1518{
1508 via82xx_t *chip = snd_kcontrol_chip(kcontrol); 1519 via82xx_t *chip = snd_kcontrol_chip(kcontrol);
1520 unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
1521 unsigned long port = chip->port + 0x10 * idx;
1522 unsigned char val;
1523 int i, change = 0;
1524
1525 for (i = 0; i < 2; i++) {
1526 val = ucontrol->value.integer.value[i];
1527 if (val > VIA_DXS_MAX_VOLUME)
1528 val = VIA_DXS_MAX_VOLUME;
1529 val = VIA_DXS_MAX_VOLUME - val;
1530 change |= val != chip->playback_volume[idx][i];
1531 if (change) {
1532 chip->playback_volume[idx][i] = val;
1533 outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
1534 }
1535 }
1536 return change;
1537}
1538
1539static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1540{
1541 via82xx_t *chip = snd_kcontrol_chip(kcontrol);
1509 unsigned int idx; 1542 unsigned int idx;
1510 unsigned char val; 1543 unsigned char val;
1511 int i, change = 0; 1544 int i, change = 0;
@@ -1515,11 +1548,12 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
1515 if (val > VIA_DXS_MAX_VOLUME) 1548 if (val > VIA_DXS_MAX_VOLUME)
1516 val = VIA_DXS_MAX_VOLUME; 1549 val = VIA_DXS_MAX_VOLUME;
1517 val = VIA_DXS_MAX_VOLUME - val; 1550 val = VIA_DXS_MAX_VOLUME - val;
1518 if (val != chip->playback_volume[i]) { 1551 if (val != chip->playback_volume_c[i]) {
1519 change = 1; 1552 change = 1;
1520 chip->playback_volume[i] = val; 1553 chip->playback_volume_c[i] = val;
1521 for (idx = 0; idx < 4; idx++) { 1554 for (idx = 0; idx < 4; idx++) {
1522 unsigned long port = chip->port + 0x10 * idx; 1555 unsigned long port = chip->port + 0x10 * idx;
1556 chip->playback_volume[idx][i] = val;
1523 outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); 1557 outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
1524 } 1558 }
1525 } 1559 }
@@ -1527,10 +1561,19 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
1527 return change; 1561 return change;
1528} 1562}
1529 1563
1530static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { 1564static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = {
1531 .name = "PCM Playback Volume", 1565 .name = "PCM Playback Volume",
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1566 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533 .info = snd_via8233_dxs_volume_info, 1567 .info = snd_via8233_dxs_volume_info,
1568 .get = snd_via8233_pcmdxs_volume_get,
1569 .put = snd_via8233_pcmdxs_volume_put,
1570};
1571
1572static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
1573 .name = "VIA DXS Playback Volume",
1574 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1575 .count = 4,
1576 .info = snd_via8233_dxs_volume_info,
1534 .get = snd_via8233_dxs_volume_get, 1577 .get = snd_via8233_dxs_volume_get,
1535 .put = snd_via8233_dxs_volume_put, 1578 .put = snd_via8233_dxs_volume_put,
1536}; 1579};
@@ -1723,12 +1766,19 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip)
1723 strcpy(sid.name, "PCM Playback Volume"); 1766 strcpy(sid.name, "PCM Playback Volume");
1724 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1767 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1725 if (! snd_ctl_find_id(chip->card, &sid)) { 1768 if (! snd_ctl_find_id(chip->card, &sid)) {
1769 snd_printd(KERN_INFO "Using DXS as PCM Playback\n");
1770 err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip));
1771 if (err < 0)
1772 return err;
1773 }
1774 else /* Using DXS when PCM emulation is enabled is really weird */
1775 {
1776 /* Standalone DXS controls */
1726 err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); 1777 err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
1727 if (err < 0) 1778 if (err < 0)
1728 return err; 1779 return err;
1729 } 1780 }
1730 } 1781 }
1731
1732 /* select spdif data slot 10/11 */ 1782 /* select spdif data slot 10/11 */
1733 pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); 1783 pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
1734 val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; 1784 val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;
@@ -1941,8 +1991,10 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
1941 int i, idx; 1991 int i, idx;
1942 for (idx = 0; idx < 4; idx++) { 1992 for (idx = 0; idx < 4; idx++) {
1943 unsigned long port = chip->port + 0x10 * idx; 1993 unsigned long port = chip->port + 0x10 * idx;
1944 for (i = 0; i < 2; i++) 1994 for (i = 0; i < 2; i++) {
1945 outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); 1995 chip->playback_volume[idx][i]=chip->playback_volume_c[i];
1996 outb(chip->playback_volume_c[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
1997 }
1946 } 1998 }
1947 } 1999 }
1948 2000