Commit 30bdee0259093e114c711943902c834e5c3326c5
1 parent
85e4d95da0
Exists in
master
and in
6 other branches
ALSA: es1968,maestro3 - Use work for hw-volume control
Instead of tasklet, use workq for handling the hw-volume control. This reduces lots of spinlocks. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 2 changed files with 23 additions and 112 deletions Side-by-side Diff
sound/pci/es1968.c
... | ... | @@ -554,9 +554,8 @@ |
554 | 554 | #else |
555 | 555 | struct snd_kcontrol *master_switch; /* for h/w volume control */ |
556 | 556 | struct snd_kcontrol *master_volume; |
557 | - spinlock_t ac97_lock; | |
558 | - struct tasklet_struct hwvol_tq; | |
559 | 557 | #endif |
558 | + struct work_struct hwvol_work; | |
560 | 559 | |
561 | 560 | #ifdef CONFIG_SND_ES1968_RADIO |
562 | 561 | struct snd_tea575x tea; |
563 | 562 | |
564 | 563 | |
565 | 564 | |
566 | 565 | |
... | ... | @@ -646,38 +645,23 @@ |
646 | 645 | static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) |
647 | 646 | { |
648 | 647 | struct es1968 *chip = ac97->private_data; |
649 | -#ifndef CONFIG_SND_ES1968_INPUT | |
650 | - unsigned long flags; | |
651 | -#endif | |
652 | 648 | |
653 | 649 | snd_es1968_ac97_wait(chip); |
654 | 650 | |
655 | 651 | /* Write the bus */ |
656 | -#ifndef CONFIG_SND_ES1968_INPUT | |
657 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
658 | -#endif | |
659 | 652 | outw(val, chip->io_port + ESM_AC97_DATA); |
660 | 653 | /*msleep(1);*/ |
661 | 654 | outb(reg, chip->io_port + ESM_AC97_INDEX); |
662 | 655 | /*msleep(1);*/ |
663 | -#ifndef CONFIG_SND_ES1968_INPUT | |
664 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
665 | -#endif | |
666 | 656 | } |
667 | 657 | |
668 | 658 | static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
669 | 659 | { |
670 | 660 | u16 data = 0; |
671 | 661 | struct es1968 *chip = ac97->private_data; |
672 | -#ifndef CONFIG_SND_ES1968_INPUT | |
673 | - unsigned long flags; | |
674 | -#endif | |
675 | 662 | |
676 | 663 | snd_es1968_ac97_wait(chip); |
677 | 664 | |
678 | -#ifndef CONFIG_SND_ES1968_INPUT | |
679 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
680 | -#endif | |
681 | 665 | outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); |
682 | 666 | /*msleep(1);*/ |
683 | 667 | |
... | ... | @@ -685,9 +669,6 @@ |
685 | 669 | data = inw(chip->io_port + ESM_AC97_DATA); |
686 | 670 | /*msleep(1);*/ |
687 | 671 | } |
688 | -#ifndef CONFIG_SND_ES1968_INPUT | |
689 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
690 | -#endif | |
691 | 672 | |
692 | 673 | return data; |
693 | 674 | } |
694 | 675 | |
695 | 676 | |
... | ... | @@ -1904,13 +1885,10 @@ |
1904 | 1885 | (without wrap around) in response to volume button presses and then |
1905 | 1886 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 |
1906 | 1887 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ |
1907 | -static void es1968_update_hw_volume(unsigned long private_data) | |
1888 | +static void es1968_update_hw_volume(struct work_struct *work) | |
1908 | 1889 | { |
1909 | - struct es1968 *chip = (struct es1968 *) private_data; | |
1890 | + struct es1968 *chip = container_of(work, struct es1968, hwvol_work); | |
1910 | 1891 | int x, val; |
1911 | -#ifndef CONFIG_SND_ES1968_INPUT | |
1912 | - unsigned long flags; | |
1913 | -#endif | |
1914 | 1892 | |
1915 | 1893 | /* Figure out which volume control button was pushed, |
1916 | 1894 | based on differences from the default register |
1917 | 1895 | |
... | ... | @@ -1929,18 +1907,11 @@ |
1929 | 1907 | if (! chip->master_switch || ! chip->master_volume) |
1930 | 1908 | return; |
1931 | 1909 | |
1932 | - /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | |
1933 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
1934 | - val = chip->ac97->regs[AC97_MASTER]; | |
1910 | + val = snd_ac97_read(chip->ac97, AC97_MASTER); | |
1935 | 1911 | switch (x) { |
1936 | 1912 | case 0x88: |
1937 | 1913 | /* mute */ |
1938 | 1914 | val ^= 0x8000; |
1939 | - chip->ac97->regs[AC97_MASTER] = val; | |
1940 | - outw(val, chip->io_port + ESM_AC97_DATA); | |
1941 | - outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | |
1942 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1943 | - &chip->master_switch->id); | |
1944 | 1915 | break; |
1945 | 1916 | case 0xaa: |
1946 | 1917 | /* volume up */ |
... | ... | @@ -1948,11 +1919,6 @@ |
1948 | 1919 | val--; |
1949 | 1920 | if ((val & 0x7f00) > 0) |
1950 | 1921 | val -= 0x0100; |
1951 | - chip->ac97->regs[AC97_MASTER] = val; | |
1952 | - outw(val, chip->io_port + ESM_AC97_DATA); | |
1953 | - outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | |
1954 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1955 | - &chip->master_volume->id); | |
1956 | 1922 | break; |
1957 | 1923 | case 0x66: |
1958 | 1924 | /* volume down */ |
1959 | 1925 | |
... | ... | @@ -1960,14 +1926,11 @@ |
1960 | 1926 | val++; |
1961 | 1927 | if ((val & 0x7f00) < 0x1f00) |
1962 | 1928 | val += 0x0100; |
1963 | - chip->ac97->regs[AC97_MASTER] = val; | |
1964 | - outw(val, chip->io_port + ESM_AC97_DATA); | |
1965 | - outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | |
1966 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1967 | - &chip->master_volume->id); | |
1968 | 1929 | break; |
1969 | 1930 | } |
1970 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
1931 | + if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) | |
1932 | + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1933 | + &chip->master_volume->id); | |
1971 | 1934 | #else |
1972 | 1935 | if (!chip->input_dev) |
1973 | 1936 | return; |
... | ... | @@ -2013,11 +1976,7 @@ |
2013 | 1976 | outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); |
2014 | 1977 | |
2015 | 1978 | if (event & ESM_HWVOL_IRQ) |
2016 | -#ifdef CONFIG_SND_ES1968_INPUT | |
2017 | - es1968_update_hw_volume((unsigned long)chip); | |
2018 | -#else | |
2019 | - tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */ | |
2020 | -#endif | |
1979 | + schedule_work(&chip->hwvol_work); | |
2021 | 1980 | |
2022 | 1981 | /* else ack 'em all, i imagine */ |
2023 | 1982 | outb(0xFF, chip->io_port + 0x1A); |
... | ... | @@ -2426,6 +2385,7 @@ |
2426 | 2385 | return 0; |
2427 | 2386 | |
2428 | 2387 | chip->in_suspend = 1; |
2388 | + cancel_work_sync(&chip->hwvol_work); | |
2429 | 2389 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2430 | 2390 | snd_pcm_suspend_all(chip->pcm); |
2431 | 2391 | snd_ac97_suspend(chip->ac97); |
... | ... | @@ -2638,6 +2598,7 @@ |
2638 | 2598 | |
2639 | 2599 | static int snd_es1968_free(struct es1968 *chip) |
2640 | 2600 | { |
2601 | + cancel_work_sync(&chip->hwvol_work); | |
2641 | 2602 | #ifdef CONFIG_SND_ES1968_INPUT |
2642 | 2603 | if (chip->input_dev) |
2643 | 2604 | input_unregister_device(chip->input_dev); |
... | ... | @@ -2728,10 +2689,7 @@ |
2728 | 2689 | INIT_LIST_HEAD(&chip->buf_list); |
2729 | 2690 | INIT_LIST_HEAD(&chip->substream_list); |
2730 | 2691 | mutex_init(&chip->memory_mutex); |
2731 | -#ifndef CONFIG_SND_ES1968_INPUT | |
2732 | - spin_lock_init(&chip->ac97_lock); | |
2733 | - tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); | |
2734 | -#endif | |
2692 | + INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume); | |
2735 | 2693 | chip->card = card; |
2736 | 2694 | chip->pci = pci; |
2737 | 2695 | chip->irq = -1; |
sound/pci/maestro3.c
... | ... | @@ -850,11 +850,10 @@ |
850 | 850 | struct input_dev *input_dev; |
851 | 851 | char phys[64]; /* physical device path */ |
852 | 852 | #else |
853 | - spinlock_t ac97_lock; | |
854 | 853 | struct snd_kcontrol *master_switch; |
855 | 854 | struct snd_kcontrol *master_volume; |
856 | - struct tasklet_struct hwvol_tq; | |
857 | 855 | #endif |
856 | + struct work_struct hwvol_work; | |
858 | 857 | |
859 | 858 | unsigned int in_suspend; |
860 | 859 | |
861 | 860 | |
862 | 861 | |
... | ... | @@ -1609,13 +1608,10 @@ |
1609 | 1608 | (without wrap around) in response to volume button presses and then |
1610 | 1609 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 |
1611 | 1610 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ |
1612 | -static void snd_m3_update_hw_volume(unsigned long private_data) | |
1611 | +static void snd_m3_update_hw_volume(struct work_struct *work) | |
1613 | 1612 | { |
1614 | - struct snd_m3 *chip = (struct snd_m3 *) private_data; | |
1613 | + struct snd_m3 *chip = container_of(work, struct snd_m3, hwvol_work); | |
1615 | 1614 | int x, val; |
1616 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
1617 | - unsigned long flags; | |
1618 | -#endif | |
1619 | 1615 | |
1620 | 1616 | /* Figure out which volume control button was pushed, |
1621 | 1617 | based on differences from the default register |
1622 | 1618 | |
... | ... | @@ -1645,21 +1641,13 @@ |
1645 | 1641 | if (!chip->master_switch || !chip->master_volume) |
1646 | 1642 | return; |
1647 | 1643 | |
1648 | - /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | |
1649 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
1650 | - | |
1651 | - val = chip->ac97->regs[AC97_MASTER_VOL]; | |
1644 | + val = snd_ac97_read(chip->ac97, AC97_MASTER); | |
1652 | 1645 | switch (x) { |
1653 | 1646 | case 0x88: |
1654 | 1647 | /* The counters have not changed, yet we've received a HV |
1655 | 1648 | interrupt. According to tests run by various people this |
1656 | 1649 | happens when pressing the mute button. */ |
1657 | 1650 | val ^= 0x8000; |
1658 | - chip->ac97->regs[AC97_MASTER_VOL] = val; | |
1659 | - outw(val, chip->iobase + CODEC_DATA); | |
1660 | - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | |
1661 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1662 | - &chip->master_switch->id); | |
1663 | 1651 | break; |
1664 | 1652 | case 0xaa: |
1665 | 1653 | /* counters increased by 1 -> volume up */ |
... | ... | @@ -1667,11 +1655,6 @@ |
1667 | 1655 | val--; |
1668 | 1656 | if ((val & 0x7f00) > 0) |
1669 | 1657 | val -= 0x0100; |
1670 | - chip->ac97->regs[AC97_MASTER_VOL] = val; | |
1671 | - outw(val, chip->iobase + CODEC_DATA); | |
1672 | - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | |
1673 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1674 | - &chip->master_volume->id); | |
1675 | 1658 | break; |
1676 | 1659 | case 0x66: |
1677 | 1660 | /* counters decreased by 1 -> volume down */ |
1678 | 1661 | |
... | ... | @@ -1679,14 +1662,11 @@ |
1679 | 1662 | val++; |
1680 | 1663 | if ((val & 0x7f00) < 0x1f00) |
1681 | 1664 | val += 0x0100; |
1682 | - chip->ac97->regs[AC97_MASTER_VOL] = val; | |
1683 | - outw(val, chip->iobase + CODEC_DATA); | |
1684 | - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | |
1685 | - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1686 | - &chip->master_volume->id); | |
1687 | 1665 | break; |
1688 | 1666 | } |
1689 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
1667 | + if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) | |
1668 | + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | |
1669 | + &chip->master_switch->id); | |
1690 | 1670 | #else |
1691 | 1671 | if (!chip->input_dev) |
1692 | 1672 | return; |
... | ... | @@ -1730,11 +1710,7 @@ |
1730 | 1710 | return IRQ_NONE; |
1731 | 1711 | |
1732 | 1712 | if (status & HV_INT_PENDING) |
1733 | -#ifdef CONFIG_SND_MAESTRO3_INPUT | |
1734 | - snd_m3_update_hw_volume((unsigned long)chip); | |
1735 | -#else | |
1736 | - tasklet_schedule(&chip->hwvol_tq); | |
1737 | -#endif | |
1713 | + schedule_work(&chip->hwvol_work); | |
1738 | 1714 | |
1739 | 1715 | /* |
1740 | 1716 | * ack an assp int if its running |
1741 | 1717 | |
1742 | 1718 | |
1743 | 1719 | |
... | ... | @@ -2000,24 +1976,14 @@ |
2000 | 1976 | snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
2001 | 1977 | { |
2002 | 1978 | struct snd_m3 *chip = ac97->private_data; |
2003 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2004 | - unsigned long flags; | |
2005 | -#endif | |
2006 | 1979 | unsigned short data = 0xffff; |
2007 | 1980 | |
2008 | 1981 | if (snd_m3_ac97_wait(chip)) |
2009 | 1982 | goto fail; |
2010 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2011 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
2012 | -#endif | |
2013 | 1983 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); |
2014 | 1984 | if (snd_m3_ac97_wait(chip)) |
2015 | - goto fail_unlock; | |
1985 | + goto fail; | |
2016 | 1986 | data = snd_m3_inw(chip, CODEC_DATA); |
2017 | -fail_unlock: | |
2018 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2019 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
2020 | -#endif | |
2021 | 1987 | fail: |
2022 | 1988 | return data; |
2023 | 1989 | } |
2024 | 1990 | |
2025 | 1991 | |
... | ... | @@ -2026,20 +1992,11 @@ |
2026 | 1992 | snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) |
2027 | 1993 | { |
2028 | 1994 | struct snd_m3 *chip = ac97->private_data; |
2029 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2030 | - unsigned long flags; | |
2031 | -#endif | |
2032 | 1995 | |
2033 | 1996 | if (snd_m3_ac97_wait(chip)) |
2034 | 1997 | return; |
2035 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2036 | - spin_lock_irqsave(&chip->ac97_lock, flags); | |
2037 | -#endif | |
2038 | 1998 | snd_m3_outw(chip, val, CODEC_DATA); |
2039 | 1999 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); |
2040 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2041 | - spin_unlock_irqrestore(&chip->ac97_lock, flags); | |
2042 | -#endif | |
2043 | 2000 | } |
2044 | 2001 | |
2045 | 2002 | |
... | ... | @@ -2458,6 +2415,7 @@ |
2458 | 2415 | struct m3_dma *s; |
2459 | 2416 | int i; |
2460 | 2417 | |
2418 | + cancel_work_sync(&chip->hwvol_work); | |
2461 | 2419 | #ifdef CONFIG_SND_MAESTRO3_INPUT |
2462 | 2420 | if (chip->input_dev) |
2463 | 2421 | input_unregister_device(chip->input_dev); |
... | ... | @@ -2511,6 +2469,7 @@ |
2511 | 2469 | return 0; |
2512 | 2470 | |
2513 | 2471 | chip->in_suspend = 1; |
2472 | + cancel_work_sync(&chip->hwvol_work); | |
2514 | 2473 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2515 | 2474 | snd_pcm_suspend_all(chip->pcm); |
2516 | 2475 | snd_ac97_suspend(chip->ac97); |
... | ... | @@ -2667,9 +2626,6 @@ |
2667 | 2626 | } |
2668 | 2627 | |
2669 | 2628 | spin_lock_init(&chip->reg_lock); |
2670 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2671 | - spin_lock_init(&chip->ac97_lock); | |
2672 | -#endif | |
2673 | 2629 | |
2674 | 2630 | switch (pci->device) { |
2675 | 2631 | case PCI_DEVICE_ID_ESS_ALLEGRO: |
... | ... | @@ -2683,6 +2639,7 @@ |
2683 | 2639 | chip->card = card; |
2684 | 2640 | chip->pci = pci; |
2685 | 2641 | chip->irq = -1; |
2642 | + INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume); | |
2686 | 2643 | |
2687 | 2644 | chip->external_amp = enable_amp; |
2688 | 2645 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) |
... | ... | @@ -2751,10 +2708,6 @@ |
2751 | 2708 | snd_m3_amp_enable(chip, 1); |
2752 | 2709 | |
2753 | 2710 | snd_m3_hv_init(chip); |
2754 | - | |
2755 | -#ifndef CONFIG_SND_MAESTRO3_INPUT | |
2756 | - tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | |
2757 | -#endif | |
2758 | 2711 | |
2759 | 2712 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, |
2760 | 2713 | KBUILD_MODNAME, chip)) { |