diff options
author | Ville Syrjälä <syrjala@sci.fi> | 2008-06-03 13:52:10 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-06-06 05:54:18 -0400 |
commit | 8b83afe0d21f07145ec34ac006656e4d3edc4bac (patch) | |
tree | 307a313a408d914ff1d10cd7e0c595ca39ef3c21 | |
parent | 607d982bbea2a14b5b77cc7689f509d588e1e6da (diff) |
[ALSA] maestro3: Fix hw volume on HP OmniBook
Make the hw volume buttons work correctly on some HP OmniBook laptops.
The original quirk was apparently applied a bit too early and it was
also lacking some critial register writes. This improved sequence was
discovered by trial and error (like the original sequence). Tested and
found working on OB500 and OB6000 laptops.
Signed-off-by: Ville Syrjala <syrjala@sci.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/maestro3.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index a536c59fbea1..f4788dee05c3 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2427,6 +2427,29 @@ snd_m3_amp_enable(struct snd_m3 *chip, int enable) | |||
2427 | outw(0xffff, io + GPIO_MASK); | 2427 | outw(0xffff, io + GPIO_MASK); |
2428 | } | 2428 | } |
2429 | 2429 | ||
2430 | static void | ||
2431 | snd_m3_hv_init(struct snd_m3 *chip) | ||
2432 | { | ||
2433 | unsigned long io = chip->iobase; | ||
2434 | u16 val = GPI_VOL_DOWN | GPI_VOL_UP; | ||
2435 | |||
2436 | if (!chip->is_omnibook) | ||
2437 | return; | ||
2438 | |||
2439 | /* | ||
2440 | * Volume buttons on some HP OmniBook laptops | ||
2441 | * require some GPIO magic to work correctly. | ||
2442 | */ | ||
2443 | outw(0xffff, io + GPIO_MASK); | ||
2444 | outw(0x0000, io + GPIO_DATA); | ||
2445 | |||
2446 | outw(~val, io + GPIO_MASK); | ||
2447 | outw(inw(io + GPIO_DIRECTION) & ~val, io + GPIO_DIRECTION); | ||
2448 | outw(val, io + GPIO_MASK); | ||
2449 | |||
2450 | outw(0xffff, io + GPIO_MASK); | ||
2451 | } | ||
2452 | |||
2430 | static int | 2453 | static int |
2431 | snd_m3_chip_init(struct snd_m3 *chip) | 2454 | snd_m3_chip_init(struct snd_m3 *chip) |
2432 | { | 2455 | { |
@@ -2442,21 +2465,6 @@ snd_m3_chip_init(struct snd_m3 *chip) | |||
2442 | DISABLE_LEGACY); | 2465 | DISABLE_LEGACY); |
2443 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); | 2466 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); |
2444 | 2467 | ||
2445 | if (chip->is_omnibook) { | ||
2446 | /* | ||
2447 | * Volume buttons on some HP OmniBook laptops don't work | ||
2448 | * correctly. This makes them work for the most part. | ||
2449 | * | ||
2450 | * Volume up and down buttons on the laptop side work. | ||
2451 | * Fn+cursor_up (volme up) works. | ||
2452 | * Fn+cursor_down (volume down) doesn't work. | ||
2453 | * Fn+F7 (mute) works acts as volume up. | ||
2454 | */ | ||
2455 | outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK); | ||
2456 | outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION); | ||
2457 | outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA); | ||
2458 | outw(0xffff, io + GPIO_MASK); | ||
2459 | } | ||
2460 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); | 2468 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); |
2461 | n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); | 2469 | n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); |
2462 | n |= chip->hv_config; | 2470 | n |= chip->hv_config; |
@@ -2642,6 +2650,8 @@ static int m3_resume(struct pci_dev *pci) | |||
2642 | snd_m3_enable_ints(chip); | 2650 | snd_m3_enable_ints(chip); |
2643 | snd_m3_amp_enable(chip, 1); | 2651 | snd_m3_amp_enable(chip, 1); |
2644 | 2652 | ||
2653 | snd_m3_hv_init(chip); | ||
2654 | |||
2645 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2655 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2646 | return 0; | 2656 | return 0; |
2647 | } | 2657 | } |
@@ -2781,6 +2791,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2781 | 2791 | ||
2782 | snd_m3_amp_enable(chip, 1); | 2792 | snd_m3_amp_enable(chip, 1); |
2783 | 2793 | ||
2794 | snd_m3_hv_init(chip); | ||
2795 | |||
2784 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | 2796 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); |
2785 | 2797 | ||
2786 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, | 2798 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, |