diff options
| author | Hans de Goede <hdegoede@redhat.com> | 2010-04-21 11:04:07 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2010-04-22 10:53:38 -0400 |
| commit | 20133d4cd329af7a02ee5af36bba1796d5ff7b1d (patch) | |
| tree | 25d1c3b9babba2203b9ee60451647d8ae3b4af23 | |
| parent | 6458a54423f9a4963e7e88ff62040117285e6b8c (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>
| -rw-r--r-- | sound/pci/maestro3.c | 22 |
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. */ | ||
| 1601 | static void snd_m3_update_hw_volume(unsigned long private_data) | 1605 | static 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) |
