Commit 30bdee0259093e114c711943902c834e5c3326c5

Authored by Takashi Iwai
1 parent 85e4d95da0

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

... ... @@ -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)) {