aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/maestro3.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-06-14 07:57:02 -0400
committerTakashi Iwai <tiwai@suse.de>2011-06-14 07:59:51 -0400
commit30bdee0259093e114c711943902c834e5c3326c5 (patch)
treedb5f4c2eb1459a1ad210d8ae094c8e515141d6e8 /sound/pci/maestro3.c
parent85e4d95da091e35209338962eca232e70819a485 (diff)
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>
Diffstat (limited to 'sound/pci/maestro3.c')
-rw-r--r--sound/pci/maestro3.c71
1 files changed, 12 insertions, 59 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 64f6f627f4c2..0378126e6272 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -850,11 +850,10 @@ struct snd_m3 {
850 struct input_dev *input_dev; 850 struct input_dev *input_dev;
851 char phys[64]; /* physical device path */ 851 char phys[64]; /* physical device path */
852#else 852#else
853 spinlock_t ac97_lock;
854 struct snd_kcontrol *master_switch; 853 struct snd_kcontrol *master_switch;
855 struct snd_kcontrol *master_volume; 854 struct snd_kcontrol *master_volume;
856 struct tasklet_struct hwvol_tq;
857#endif 855#endif
856 struct work_struct hwvol_work;
858 857
859 unsigned int in_suspend; 858 unsigned int in_suspend;
860 859
@@ -1609,13 +1608,10 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
1609 (without wrap around) in response to volume button presses and then 1608 (without wrap around) in response to volume button presses and then
1610 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 1609 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1611 of a byte wide register. The meaning of bits 0 and 4 is unknown. */ 1610 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1612static void snd_m3_update_hw_volume(unsigned long private_data) 1611static 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 int x, val; 1614 int x, val;
1616#ifndef CONFIG_SND_MAESTRO3_INPUT
1617 unsigned long flags;
1618#endif
1619 1615
1620 /* Figure out which volume control button was pushed, 1616 /* Figure out which volume control button was pushed,
1621 based on differences from the default register 1617 based on differences from the default register
@@ -1645,21 +1641,13 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1645 if (!chip->master_switch || !chip->master_volume) 1641 if (!chip->master_switch || !chip->master_volume)
1646 return; 1642 return;
1647 1643
1648 /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ 1644 val = snd_ac97_read(chip->ac97, AC97_MASTER);
1649 spin_lock_irqsave(&chip->ac97_lock, flags);
1650
1651 val = chip->ac97->regs[AC97_MASTER_VOL];
1652 switch (x) { 1645 switch (x) {
1653 case 0x88: 1646 case 0x88:
1654 /* The counters have not changed, yet we've received a HV 1647 /* The counters have not changed, yet we've received a HV
1655 interrupt. According to tests run by various people this 1648 interrupt. According to tests run by various people this
1656 happens when pressing the mute button. */ 1649 happens when pressing the mute button. */
1657 val ^= 0x8000; 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 break; 1651 break;
1664 case 0xaa: 1652 case 0xaa:
1665 /* counters increased by 1 -> volume up */ 1653 /* counters increased by 1 -> volume up */
@@ -1667,11 +1655,6 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1667 val--; 1655 val--;
1668 if ((val & 0x7f00) > 0) 1656 if ((val & 0x7f00) > 0)
1669 val -= 0x0100; 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 break; 1658 break;
1676 case 0x66: 1659 case 0x66:
1677 /* counters decreased by 1 -> volume down */ 1660 /* counters decreased by 1 -> volume down */
@@ -1679,14 +1662,11 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1679 val++; 1662 val++;
1680 if ((val & 0x7f00) < 0x1f00) 1663 if ((val & 0x7f00) < 0x1f00)
1681 val += 0x0100; 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 break; 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#else 1670#else
1691 if (!chip->input_dev) 1671 if (!chip->input_dev)
1692 return; 1672 return;
@@ -1730,11 +1710,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
1730 return IRQ_NONE; 1710 return IRQ_NONE;
1731 1711
1732 if (status & HV_INT_PENDING) 1712 if (status & HV_INT_PENDING)
1733#ifdef CONFIG_SND_MAESTRO3_INPUT 1713 schedule_work(&chip->hwvol_work);
1734 snd_m3_update_hw_volume((unsigned long)chip);
1735#else
1736 tasklet_schedule(&chip->hwvol_tq);
1737#endif
1738 1714
1739 /* 1715 /*
1740 * ack an assp int if its running 1716 * ack an assp int if its running
@@ -2000,24 +1976,14 @@ static unsigned short
2000snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 1976snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
2001{ 1977{
2002 struct snd_m3 *chip = ac97->private_data; 1978 struct snd_m3 *chip = ac97->private_data;
2003#ifndef CONFIG_SND_MAESTRO3_INPUT
2004 unsigned long flags;
2005#endif
2006 unsigned short data = 0xffff; 1979 unsigned short data = 0xffff;
2007 1980
2008 if (snd_m3_ac97_wait(chip)) 1981 if (snd_m3_ac97_wait(chip))
2009 goto fail; 1982 goto fail;
2010#ifndef CONFIG_SND_MAESTRO3_INPUT
2011 spin_lock_irqsave(&chip->ac97_lock, flags);
2012#endif
2013 snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); 1983 snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
2014 if (snd_m3_ac97_wait(chip)) 1984 if (snd_m3_ac97_wait(chip))
2015 goto fail_unlock; 1985 goto fail;
2016 data = snd_m3_inw(chip, CODEC_DATA); 1986 data = snd_m3_inw(chip, CODEC_DATA);
2017fail_unlock:
2018#ifndef CONFIG_SND_MAESTRO3_INPUT
2019 spin_unlock_irqrestore(&chip->ac97_lock, flags);
2020#endif
2021fail: 1987fail:
2022 return data; 1988 return data;
2023} 1989}
@@ -2026,20 +1992,11 @@ static void
2026snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 1992snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
2027{ 1993{
2028 struct snd_m3 *chip = ac97->private_data; 1994 struct snd_m3 *chip = ac97->private_data;
2029#ifndef CONFIG_SND_MAESTRO3_INPUT
2030 unsigned long flags;
2031#endif
2032 1995
2033 if (snd_m3_ac97_wait(chip)) 1996 if (snd_m3_ac97_wait(chip))
2034 return; 1997 return;
2035#ifndef CONFIG_SND_MAESTRO3_INPUT
2036 spin_lock_irqsave(&chip->ac97_lock, flags);
2037#endif
2038 snd_m3_outw(chip, val, CODEC_DATA); 1998 snd_m3_outw(chip, val, CODEC_DATA);
2039 snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); 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 @@ static int snd_m3_free(struct snd_m3 *chip)
2458 struct m3_dma *s; 2415 struct m3_dma *s;
2459 int i; 2416 int i;
2460 2417
2418 cancel_work_sync(&chip->hwvol_work);
2461#ifdef CONFIG_SND_MAESTRO3_INPUT 2419#ifdef CONFIG_SND_MAESTRO3_INPUT
2462 if (chip->input_dev) 2420 if (chip->input_dev)
2463 input_unregister_device(chip->input_dev); 2421 input_unregister_device(chip->input_dev);
@@ -2511,6 +2469,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
2511 return 0; 2469 return 0;
2512 2470
2513 chip->in_suspend = 1; 2471 chip->in_suspend = 1;
2472 cancel_work_sync(&chip->hwvol_work);
2514 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2473 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
2515 snd_pcm_suspend_all(chip->pcm); 2474 snd_pcm_suspend_all(chip->pcm);
2516 snd_ac97_suspend(chip->ac97); 2475 snd_ac97_suspend(chip->ac97);
@@ -2667,9 +2626,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2667 } 2626 }
2668 2627
2669 spin_lock_init(&chip->reg_lock); 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 switch (pci->device) { 2630 switch (pci->device) {
2675 case PCI_DEVICE_ID_ESS_ALLEGRO: 2631 case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2683,6 +2639,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2683 chip->card = card; 2639 chip->card = card;
2684 chip->pci = pci; 2640 chip->pci = pci;
2685 chip->irq = -1; 2641 chip->irq = -1;
2642 INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
2686 2643
2687 chip->external_amp = enable_amp; 2644 chip->external_amp = enable_amp;
2688 if (amp_gpio >= 0 && amp_gpio <= 0x0f) 2645 if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2752,10 +2709,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2752 2709
2753 snd_m3_hv_init(chip); 2710 snd_m3_hv_init(chip);
2754 2711
2755#ifndef CONFIG_SND_MAESTRO3_INPUT
2756 tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
2757#endif
2758
2759 if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, 2712 if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
2760 KBUILD_MODNAME, chip)) { 2713 KBUILD_MODNAME, chip)) {
2761 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 2714 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);