aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/es1968.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/es1968.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/es1968.c')
-rw-r--r--sound/pci/es1968.c64
1 files changed, 11 insertions, 53 deletions
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 3fa46593a3b9..99ea9320c6b5 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -554,9 +554,8 @@ struct es1968 {
554#else 554#else
555 struct snd_kcontrol *master_switch; /* for h/w volume control */ 555 struct snd_kcontrol *master_switch; /* for h/w volume control */
556 struct snd_kcontrol *master_volume; 556 struct snd_kcontrol *master_volume;
557 spinlock_t ac97_lock;
558 struct tasklet_struct hwvol_tq;
559#endif 557#endif
558 struct work_struct hwvol_work;
560 559
561#ifdef CONFIG_SND_ES1968_RADIO 560#ifdef CONFIG_SND_ES1968_RADIO
562 struct snd_tea575x tea; 561 struct snd_tea575x tea;
@@ -646,38 +645,23 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip)
646static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 645static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
647{ 646{
648 struct es1968 *chip = ac97->private_data; 647 struct es1968 *chip = ac97->private_data;
649#ifndef CONFIG_SND_ES1968_INPUT
650 unsigned long flags;
651#endif
652 648
653 snd_es1968_ac97_wait(chip); 649 snd_es1968_ac97_wait(chip);
654 650
655 /* Write the bus */ 651 /* Write the bus */
656#ifndef CONFIG_SND_ES1968_INPUT
657 spin_lock_irqsave(&chip->ac97_lock, flags);
658#endif
659 outw(val, chip->io_port + ESM_AC97_DATA); 652 outw(val, chip->io_port + ESM_AC97_DATA);
660 /*msleep(1);*/ 653 /*msleep(1);*/
661 outb(reg, chip->io_port + ESM_AC97_INDEX); 654 outb(reg, chip->io_port + ESM_AC97_INDEX);
662 /*msleep(1);*/ 655 /*msleep(1);*/
663#ifndef CONFIG_SND_ES1968_INPUT
664 spin_unlock_irqrestore(&chip->ac97_lock, flags);
665#endif
666} 656}
667 657
668static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 658static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
669{ 659{
670 u16 data = 0; 660 u16 data = 0;
671 struct es1968 *chip = ac97->private_data; 661 struct es1968 *chip = ac97->private_data;
672#ifndef CONFIG_SND_ES1968_INPUT
673 unsigned long flags;
674#endif
675 662
676 snd_es1968_ac97_wait(chip); 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 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); 665 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
682 /*msleep(1);*/ 666 /*msleep(1);*/
683 667
@@ -685,9 +669,6 @@ static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short
685 data = inw(chip->io_port + ESM_AC97_DATA); 669 data = inw(chip->io_port + ESM_AC97_DATA);
686 /*msleep(1);*/ 670 /*msleep(1);*/
687 } 671 }
688#ifndef CONFIG_SND_ES1968_INPUT
689 spin_unlock_irqrestore(&chip->ac97_lock, flags);
690#endif
691 672
692 return data; 673 return data;
693} 674}
@@ -1904,13 +1885,10 @@ static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
1904 (without wrap around) in response to volume button presses and then 1885 (without wrap around) in response to volume button presses and then
1905 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 1886 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1906 of a byte wide register. The meaning of bits 0 and 4 is unknown. */ 1887 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1907static void es1968_update_hw_volume(unsigned long private_data) 1888static 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 int x, val; 1891 int x, val;
1911#ifndef CONFIG_SND_ES1968_INPUT
1912 unsigned long flags;
1913#endif
1914 1892
1915 /* Figure out which volume control button was pushed, 1893 /* Figure out which volume control button was pushed,
1916 based on differences from the default register 1894 based on differences from the default register
@@ -1929,18 +1907,11 @@ static void es1968_update_hw_volume(unsigned long private_data)
1929 if (! chip->master_switch || ! chip->master_volume) 1907 if (! chip->master_switch || ! chip->master_volume)
1930 return; 1908 return;
1931 1909
1932 /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ 1910 val = snd_ac97_read(chip->ac97, AC97_MASTER);
1933 spin_lock_irqsave(&chip->ac97_lock, flags);
1934 val = chip->ac97->regs[AC97_MASTER];
1935 switch (x) { 1911 switch (x) {
1936 case 0x88: 1912 case 0x88:
1937 /* mute */ 1913 /* mute */
1938 val ^= 0x8000; 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 break; 1915 break;
1945 case 0xaa: 1916 case 0xaa:
1946 /* volume up */ 1917 /* volume up */
@@ -1948,11 +1919,6 @@ static void es1968_update_hw_volume(unsigned long private_data)
1948 val--; 1919 val--;
1949 if ((val & 0x7f00) > 0) 1920 if ((val & 0x7f00) > 0)
1950 val -= 0x0100; 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 break; 1922 break;
1957 case 0x66: 1923 case 0x66:
1958 /* volume down */ 1924 /* volume down */
@@ -1960,14 +1926,11 @@ static void es1968_update_hw_volume(unsigned long private_data)
1960 val++; 1926 val++;
1961 if ((val & 0x7f00) < 0x1f00) 1927 if ((val & 0x7f00) < 0x1f00)
1962 val += 0x0100; 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 break; 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#else 1934#else
1972 if (!chip->input_dev) 1935 if (!chip->input_dev)
1973 return; 1936 return;
@@ -2013,11 +1976,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
2013 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); 1976 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
2014 1977
2015 if (event & ESM_HWVOL_IRQ) 1978 if (event & ESM_HWVOL_IRQ)
2016#ifdef CONFIG_SND_ES1968_INPUT 1979 schedule_work(&chip->hwvol_work);
2017 es1968_update_hw_volume((unsigned long)chip);
2018#else
2019 tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */
2020#endif
2021 1980
2022 /* else ack 'em all, i imagine */ 1981 /* else ack 'em all, i imagine */
2023 outb(0xFF, chip->io_port + 0x1A); 1982 outb(0xFF, chip->io_port + 0x1A);
@@ -2426,6 +2385,7 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state)
2426 return 0; 2385 return 0;
2427 2386
2428 chip->in_suspend = 1; 2387 chip->in_suspend = 1;
2388 cancel_work_sync(&chip->hwvol_work);
2429 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2389 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
2430 snd_pcm_suspend_all(chip->pcm); 2390 snd_pcm_suspend_all(chip->pcm);
2431 snd_ac97_suspend(chip->ac97); 2391 snd_ac97_suspend(chip->ac97);
@@ -2638,6 +2598,7 @@ static struct snd_tea575x_ops snd_es1968_tea_ops = {
2638 2598
2639static int snd_es1968_free(struct es1968 *chip) 2599static int snd_es1968_free(struct es1968 *chip)
2640{ 2600{
2601 cancel_work_sync(&chip->hwvol_work);
2641#ifdef CONFIG_SND_ES1968_INPUT 2602#ifdef CONFIG_SND_ES1968_INPUT
2642 if (chip->input_dev) 2603 if (chip->input_dev)
2643 input_unregister_device(chip->input_dev); 2604 input_unregister_device(chip->input_dev);
@@ -2728,10 +2689,7 @@ static int __devinit snd_es1968_create(struct snd_card *card,
2728 INIT_LIST_HEAD(&chip->buf_list); 2689 INIT_LIST_HEAD(&chip->buf_list);
2729 INIT_LIST_HEAD(&chip->substream_list); 2690 INIT_LIST_HEAD(&chip->substream_list);
2730 mutex_init(&chip->memory_mutex); 2691 mutex_init(&chip->memory_mutex);
2731#ifndef CONFIG_SND_ES1968_INPUT 2692 INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume);
2732 spin_lock_init(&chip->ac97_lock);
2733 tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
2734#endif
2735 chip->card = card; 2693 chip->card = card;
2736 chip->pci = pci; 2694 chip->pci = pci;
2737 chip->irq = -1; 2695 chip->irq = -1;