diff options
Diffstat (limited to 'sound/pci/es1968.c')
-rw-r--r-- | sound/pci/es1968.c | 128 |
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 | ||
552 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); | 558 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); |
@@ -632,28 +638,38 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip) | |||
632 | static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) | 638 | static 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 | ||
648 | static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 660 | static 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. */ | ||
1879 | static void es1968_update_hw_volume(unsigned long private_data) | 1899 | static 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 | |||
2474 | static inline void snd_es1968_free_gameport(struct es1968 *chip) { } | 2534 | static inline void snd_es1968_free_gameport(struct es1968 *chip) { } |
2475 | #endif | 2535 | #endif |
2476 | 2536 | ||
2537 | #ifdef CONFIG_SND_ES1968_INPUT | ||
2538 | static 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 | |||
2477 | static int snd_es1968_free(struct es1968 *chip) | 2573 | static 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]; |