aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/es1968.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-04-23 05:26:43 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-23 11:09:59 -0400
commit5a5e02e5095ed89a0a1f4031e7440078c209442b (patch)
tree54a6238359ec63d2221802e23e4ce6581c060d77 /sound/pci/es1968.c
parenteb581adf25fe9e42197e591926de85459e68b9fd (diff)
ALSA: snd-es1968: Make hardware volume buttons an input device (rev2)
The hardware volume handling code in essence just detects key presses, and then does some hardcoded modification of the master volume based on which key is pressed. Clearly the right thing to do here is just report these keypresses to userspace and let userspace decide what to with them. This patch adds a Kconfig option which when enabled reports the volume buttons as keypresses using an input device. When enabled this option also gets rid of the ugly direct ac97 writes from the tasklet, the ac97lock and the need for using a tasklet in general. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/es1968.c')
-rw-r--r--sound/pci/es1968.c128
1 files changed, 118 insertions, 10 deletions
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index ecaea9fb48ec..aa973cee8155 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -104,6 +104,7 @@
104#include <linux/gameport.h> 104#include <linux/gameport.h>
105#include <linux/moduleparam.h> 105#include <linux/moduleparam.h>
106#include <linux/mutex.h> 106#include <linux/mutex.h>
107#include <linux/input.h>
107 108
108#include <sound/core.h> 109#include <sound/core.h>
109#include <sound/pcm.h> 110#include <sound/pcm.h>
@@ -517,14 +518,9 @@ struct es1968 {
517 518
518 /* ALSA Stuff */ 519 /* ALSA Stuff */
519 struct snd_ac97 *ac97; 520 struct snd_ac97 *ac97;
520 struct snd_kcontrol *master_switch; /* for h/w volume control */
521 struct snd_kcontrol *master_volume;
522
523 struct snd_rawmidi *rmidi; 521 struct snd_rawmidi *rmidi;
524 522
525 spinlock_t reg_lock; 523 spinlock_t reg_lock;
526 spinlock_t ac97_lock;
527 struct tasklet_struct hwvol_tq;
528 unsigned int in_suspend; 524 unsigned int in_suspend;
529 525
530 /* Maestro Stuff */ 526 /* Maestro Stuff */
@@ -547,6 +543,16 @@ struct es1968 {
547#ifdef SUPPORT_JOYSTICK 543#ifdef SUPPORT_JOYSTICK
548 struct gameport *gameport; 544 struct gameport *gameport;
549#endif 545#endif
546
547#ifdef CONFIG_SND_ES1968_INPUT
548 struct input_dev *input_dev;
549 char phys[64]; /* physical device path */
550#else
551 struct snd_kcontrol *master_switch; /* for h/w volume control */
552 struct snd_kcontrol *master_volume;
553 spinlock_t ac97_lock;
554 struct tasklet_struct hwvol_tq;
555#endif
550}; 556};
551 557
552static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); 558static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
@@ -632,28 +638,38 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip)
632static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 638static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
633{ 639{
634 struct es1968 *chip = ac97->private_data; 640 struct es1968 *chip = ac97->private_data;
641#ifndef CONFIG_SND_ES1968_INPUT
635 unsigned long flags; 642 unsigned long flags;
643#endif
636 644
637 snd_es1968_ac97_wait(chip); 645 snd_es1968_ac97_wait(chip);
638 646
639 /* Write the bus */ 647 /* Write the bus */
648#ifndef CONFIG_SND_ES1968_INPUT
640 spin_lock_irqsave(&chip->ac97_lock, flags); 649 spin_lock_irqsave(&chip->ac97_lock, flags);
650#endif
641 outw(val, chip->io_port + ESM_AC97_DATA); 651 outw(val, chip->io_port + ESM_AC97_DATA);
642 /*msleep(1);*/ 652 /*msleep(1);*/
643 outb(reg, chip->io_port + ESM_AC97_INDEX); 653 outb(reg, chip->io_port + ESM_AC97_INDEX);
644 /*msleep(1);*/ 654 /*msleep(1);*/
655#ifndef CONFIG_SND_ES1968_INPUT
645 spin_unlock_irqrestore(&chip->ac97_lock, flags); 656 spin_unlock_irqrestore(&chip->ac97_lock, flags);
657#endif
646} 658}
647 659
648static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 660static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
649{ 661{
650 u16 data = 0; 662 u16 data = 0;
651 struct es1968 *chip = ac97->private_data; 663 struct es1968 *chip = ac97->private_data;
664#ifndef CONFIG_SND_ES1968_INPUT
652 unsigned long flags; 665 unsigned long flags;
666#endif
653 667
654 snd_es1968_ac97_wait(chip); 668 snd_es1968_ac97_wait(chip);
655 669
670#ifndef CONFIG_SND_ES1968_INPUT
656 spin_lock_irqsave(&chip->ac97_lock, flags); 671 spin_lock_irqsave(&chip->ac97_lock, flags);
672#endif
657 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); 673 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
658 /*msleep(1);*/ 674 /*msleep(1);*/
659 675
@@ -661,7 +677,9 @@ static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short
661 data = inw(chip->io_port + ESM_AC97_DATA); 677 data = inw(chip->io_port + ESM_AC97_DATA);
662 /*msleep(1);*/ 678 /*msleep(1);*/
663 } 679 }
680#ifndef CONFIG_SND_ES1968_INPUT
664 spin_unlock_irqrestore(&chip->ac97_lock, flags); 681 spin_unlock_irqrestore(&chip->ac97_lock, flags);
682#endif
665 683
666 return data; 684 return data;
667} 685}
@@ -1874,13 +1892,17 @@ static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
1874 } 1892 }
1875} 1893}
1876 1894
1877/* 1895/* The hardware volume works by incrementing / decrementing 2 counters
1878 */ 1896 (without wrap around) in response to volume button presses and then
1897 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1898 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1879static void es1968_update_hw_volume(unsigned long private_data) 1899static void es1968_update_hw_volume(unsigned long private_data)
1880{ 1900{
1881 struct es1968 *chip = (struct es1968 *) private_data; 1901 struct es1968 *chip = (struct es1968 *) private_data;
1882 int x, val; 1902 int x, val;
1903#ifndef CONFIG_SND_ES1968_INPUT
1883 unsigned long flags; 1904 unsigned long flags;
1905#endif
1884 1906
1885 /* Figure out which volume control button was pushed, 1907 /* Figure out which volume control button was pushed,
1886 based on differences from the default register 1908 based on differences from the default register
@@ -1895,6 +1917,7 @@ static void es1968_update_hw_volume(unsigned long private_data)
1895 if (chip->in_suspend) 1917 if (chip->in_suspend)
1896 return; 1918 return;
1897 1919
1920#ifndef CONFIG_SND_ES1968_INPUT
1898 if (! chip->master_switch || ! chip->master_volume) 1921 if (! chip->master_switch || ! chip->master_volume)
1899 return; 1922 return;
1900 1923
@@ -1937,6 +1960,35 @@ static void es1968_update_hw_volume(unsigned long private_data)
1937 break; 1960 break;
1938 } 1961 }
1939 spin_unlock_irqrestore(&chip->ac97_lock, flags); 1962 spin_unlock_irqrestore(&chip->ac97_lock, flags);
1963#else
1964 if (!chip->input_dev)
1965 return;
1966
1967 val = 0;
1968 switch (x) {
1969 case 0x88:
1970 /* The counters have not changed, yet we've received a HV
1971 interrupt. According to tests run by various people this
1972 happens when pressing the mute button. */
1973 val = KEY_MUTE;
1974 break;
1975 case 0xaa:
1976 /* counters increased by 1 -> volume up */
1977 val = KEY_VOLUMEUP;
1978 break;
1979 case 0x66:
1980 /* counters decreased by 1 -> volume down */
1981 val = KEY_VOLUMEDOWN;
1982 break;
1983 }
1984
1985 if (val) {
1986 input_report_key(chip->input_dev, val, 1);
1987 input_sync(chip->input_dev);
1988 input_report_key(chip->input_dev, val, 0);
1989 input_sync(chip->input_dev);
1990 }
1991#endif
1940} 1992}
1941 1993
1942/* 1994/*
@@ -1953,7 +2005,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
1953 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); 2005 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
1954 2006
1955 if (event & ESM_HWVOL_IRQ) 2007 if (event & ESM_HWVOL_IRQ)
2008#ifdef CONFIG_SND_ES1968_INPUT
2009 es1968_update_hw_volume((unsigned long)chip);
2010#else
1956 tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */ 2011 tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */
2012#endif
1957 2013
1958 /* else ack 'em all, i imagine */ 2014 /* else ack 'em all, i imagine */
1959 outb(0xFF, chip->io_port + 0x1A); 2015 outb(0xFF, chip->io_port + 0x1A);
@@ -1993,7 +2049,9 @@ snd_es1968_mixer(struct es1968 *chip)
1993{ 2049{
1994 struct snd_ac97_bus *pbus; 2050 struct snd_ac97_bus *pbus;
1995 struct snd_ac97_template ac97; 2051 struct snd_ac97_template ac97;
2052#ifndef CONFIG_SND_ES1968_INPUT
1996 struct snd_ctl_elem_id elem_id; 2053 struct snd_ctl_elem_id elem_id;
2054#endif
1997 int err; 2055 int err;
1998 static struct snd_ac97_bus_ops ops = { 2056 static struct snd_ac97_bus_ops ops = {
1999 .write = snd_es1968_ac97_write, 2057 .write = snd_es1968_ac97_write,
@@ -2009,6 +2067,7 @@ snd_es1968_mixer(struct es1968 *chip)
2009 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) 2067 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
2010 return err; 2068 return err;
2011 2069
2070#ifndef CONFIG_SND_ES1968_INPUT
2012 /* attach master switch / volumes for h/w volume control */ 2071 /* attach master switch / volumes for h/w volume control */
2013 memset(&elem_id, 0, sizeof(elem_id)); 2072 memset(&elem_id, 0, sizeof(elem_id));
2014 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2073 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -2018,6 +2077,7 @@ snd_es1968_mixer(struct es1968 *chip)
2018 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2077 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2019 strcpy(elem_id.name, "Master Playback Volume"); 2078 strcpy(elem_id.name, "Master Playback Volume");
2020 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); 2079 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
2080#endif
2021 2081
2022 return 0; 2082 return 0;
2023} 2083}
@@ -2474,8 +2534,49 @@ static inline int snd_es1968_create_gameport(struct es1968 *chip, int dev) { ret
2474static inline void snd_es1968_free_gameport(struct es1968 *chip) { } 2534static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
2475#endif 2535#endif
2476 2536
2537#ifdef CONFIG_SND_ES1968_INPUT
2538static int __devinit snd_es1968_input_register(struct es1968 *chip)
2539{
2540 struct input_dev *input_dev;
2541 int err;
2542
2543 input_dev = input_allocate_device();
2544 if (!input_dev)
2545 return -ENOMEM;
2546
2547 snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0",
2548 pci_name(chip->pci));
2549
2550 input_dev->name = chip->card->driver;
2551 input_dev->phys = chip->phys;
2552 input_dev->id.bustype = BUS_PCI;
2553 input_dev->id.vendor = chip->pci->vendor;
2554 input_dev->id.product = chip->pci->device;
2555 input_dev->dev.parent = &chip->pci->dev;
2556
2557 __set_bit(EV_KEY, input_dev->evbit);
2558 __set_bit(KEY_MUTE, input_dev->keybit);
2559 __set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
2560 __set_bit(KEY_VOLUMEUP, input_dev->keybit);
2561
2562 err = input_register_device(input_dev);
2563 if (err) {
2564 input_free_device(input_dev);
2565 return err;
2566 }
2567
2568 chip->input_dev = input_dev;
2569 return 0;
2570}
2571#endif /* CONFIG_SND_ES1968_INPUT */
2572
2477static int snd_es1968_free(struct es1968 *chip) 2573static int snd_es1968_free(struct es1968 *chip)
2478{ 2574{
2575#ifdef CONFIG_SND_ES1968_INPUT
2576 if (chip->input_dev)
2577 input_unregister_device(chip->input_dev);
2578#endif
2579
2479 if (chip->io_port) { 2580 if (chip->io_port) {
2480 if (chip->irq >= 0) 2581 if (chip->irq >= 0)
2481 synchronize_irq(chip->irq); 2582 synchronize_irq(chip->irq);
@@ -2486,8 +2587,6 @@ static int snd_es1968_free(struct es1968 *chip)
2486 if (chip->irq >= 0) 2587 if (chip->irq >= 0)
2487 free_irq(chip->irq, chip); 2588 free_irq(chip->irq, chip);
2488 snd_es1968_free_gameport(chip); 2589 snd_es1968_free_gameport(chip);
2489 chip->master_switch = NULL;
2490 chip->master_volume = NULL;
2491 pci_release_regions(chip->pci); 2590 pci_release_regions(chip->pci);
2492 pci_disable_device(chip->pci); 2591 pci_disable_device(chip->pci);
2493 kfree(chip); 2592 kfree(chip);
@@ -2558,9 +2657,11 @@ static int __devinit snd_es1968_create(struct snd_card *card,
2558 spin_lock_init(&chip->substream_lock); 2657 spin_lock_init(&chip->substream_lock);
2559 INIT_LIST_HEAD(&chip->buf_list); 2658 INIT_LIST_HEAD(&chip->buf_list);
2560 INIT_LIST_HEAD(&chip->substream_list); 2659 INIT_LIST_HEAD(&chip->substream_list);
2561 spin_lock_init(&chip->ac97_lock);
2562 mutex_init(&chip->memory_mutex); 2660 mutex_init(&chip->memory_mutex);
2661#ifndef CONFIG_SND_ES1968_INPUT
2662 spin_lock_init(&chip->ac97_lock);
2563 tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); 2663 tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
2664#endif
2564 chip->card = card; 2665 chip->card = card;
2565 chip->pci = pci; 2666 chip->pci = pci;
2566 chip->irq = -1; 2667 chip->irq = -1;
@@ -2713,6 +2814,13 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
2713 2814
2714 snd_es1968_create_gameport(chip, dev); 2815 snd_es1968_create_gameport(chip, dev);
2715 2816
2817#ifdef CONFIG_SND_ES1968_INPUT
2818 err = snd_es1968_input_register(chip);
2819 if (err)
2820 snd_printk(KERN_WARNING "Input device registration "
2821 "failed with error %i", err);
2822#endif
2823
2716 snd_es1968_start_irq(chip); 2824 snd_es1968_start_irq(chip);
2717 2825
2718 chip->clock = clock[dev]; 2826 chip->clock = clock[dev];