aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/maestro3.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-04-21 11:04:07 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-22 10:53:38 -0400
commit20133d4cd329af7a02ee5af36bba1796d5ff7b1d (patch)
tree25d1c3b9babba2203b9ee60451647d8ae3b4af23 /sound/pci/maestro3.c
parent6458a54423f9a4963e7e88ff62040117285e6b8c (diff)
ALSA: snd-meastro3: Document hardware volume control a bit
While working on a fix for the volume being muted on the allegro in my Compaq EVO N600C after suspend, I've learned a few things about the hardware volume control worth documenting. The actual fix for the suspend / resume issue is in the next patch in this set. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/maestro3.c')
-rw-r--r--sound/pci/maestro3.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index b56e33676780..53d2a5d61baf 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1598,6 +1598,10 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
1598 } 1598 }
1599} 1599}
1600 1600
1601/* The m3's hardware volume works by incrementing / decrementing 2 counters
1602 (without wrap around) in response to volume button presses and then
1603 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1604 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1601static void snd_m3_update_hw_volume(unsigned long private_data) 1605static void snd_m3_update_hw_volume(unsigned long private_data)
1602{ 1606{
1603 struct snd_m3 *chip = (struct snd_m3 *) private_data; 1607 struct snd_m3 *chip = (struct snd_m3 *) private_data;
@@ -1609,7 +1613,15 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1609 values. */ 1613 values. */
1610 x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; 1614 x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
1611 1615
1612 /* Reset the volume control registers. */ 1616 /* Reset the volume counters to 4. Tests on the allegro integrated
1617 into a Compaq N600C laptop, have revealed that:
1618 1) Writing any value will result in the 2 counters being reset to
1619 4 so writing 0x88 is not strictly necessary
1620 2) Writing to any of the 4 involved registers will reset all 4
1621 of them (and reading them always returns the same value for all
1622 of them)
1623 It could be that a maestro deviates from this, so leave the code
1624 as is. */
1613 outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); 1625 outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
1614 outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); 1626 outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
1615 outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); 1627 outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
@@ -1629,7 +1641,9 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1629 val = chip->ac97->regs[AC97_MASTER_VOL]; 1641 val = chip->ac97->regs[AC97_MASTER_VOL];
1630 switch (x) { 1642 switch (x) {
1631 case 0x88: 1643 case 0x88:
1632 /* mute */ 1644 /* The counters have not changed, yet we've received a HV
1645 interrupt. According to tests run by various people this
1646 happens when pressing the mute button. */
1633 val ^= 0x8000; 1647 val ^= 0x8000;
1634 chip->ac97->regs[AC97_MASTER_VOL] = val; 1648 chip->ac97->regs[AC97_MASTER_VOL] = val;
1635 outw(val, chip->iobase + CODEC_DATA); 1649 outw(val, chip->iobase + CODEC_DATA);
@@ -1638,7 +1652,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1638 &chip->master_switch->id); 1652 &chip->master_switch->id);
1639 break; 1653 break;
1640 case 0xaa: 1654 case 0xaa:
1641 /* volume up */ 1655 /* counters increased by 1 -> volume up */
1642 if ((val & 0x7f) > 0) 1656 if ((val & 0x7f) > 0)
1643 val--; 1657 val--;
1644 if ((val & 0x7f00) > 0) 1658 if ((val & 0x7f00) > 0)
@@ -1650,7 +1664,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1650 &chip->master_volume->id); 1664 &chip->master_volume->id);
1651 break; 1665 break;
1652 case 0x66: 1666 case 0x66:
1653 /* volume down */ 1667 /* counters decreased by 1 -> volume down */
1654 if ((val & 0x7f) < 0x1f) 1668 if ((val & 0x7f) < 0x1f)
1655 val++; 1669 val++;
1656 if ((val & 0x7f00) < 0x1f00) 1670 if ((val & 0x7f00) < 0x1f00)