sound: ymfpci: increase timer resolution to 96 kHz
Clemens Ladisch [Mon, 10 Aug 2009 08:06:53 +0000 (10:06 +0200)]
Allow the interval timer to be programmed with its full 96 kHz
precision.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

include/sound/ymfpci.h
sound/pci/ymfpci/ymfpci_main.c

index 05ead66..444cd6b 100644 (file)
@@ -331,6 +331,7 @@ struct snd_ymfpci {
        struct snd_ac97 *ac97;
        struct snd_rawmidi *rawmidi;
        struct snd_timer *timer;
+       unsigned int timer_ticks;
 
        struct pci_dev *pci;
        struct snd_card *card;
index 2f09252..5518371 100644 (file)
@@ -834,7 +834,7 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id)
        status = snd_ymfpci_readw(chip, YDSXGR_INTFLAG);
        if (status & 1) {
                if (chip->timer)
-                       snd_timer_interrupt(chip->timer, chip->timer->sticks);
+                       snd_timer_interrupt(chip->timer, chip->timer_ticks);
        }
        snd_ymfpci_writew(chip, YDSXGR_INTFLAG, status);
 
@@ -1885,8 +1885,18 @@ static int snd_ymfpci_timer_start(struct snd_timer *timer)
        unsigned int count;
 
        chip = snd_timer_chip(timer);
-       count = (timer->sticks << 1) - 1;
        spin_lock_irqsave(&chip->reg_lock, flags);
+       if (timer->sticks > 1) {
+               chip->timer_ticks = timer->sticks;
+               count = timer->sticks - 1;
+       } else {
+               /*
+                * Divisor 1 is not allowed; fake it by using divisor 2 and
+                * counting two ticks for each interrupt.
+                */
+               chip->timer_ticks = 2;
+               count = 2 - 1;
+       }
        snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count);
        snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1909,14 +1919,14 @@ static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer,
                                               unsigned long *num, unsigned long *den)
 {
        *num = 1;
-       *den = 48000;
+       *den = 96000;
        return 0;
 }
 
 static struct snd_timer_hardware snd_ymfpci_timer_hw = {
        .flags = SNDRV_TIMER_HW_AUTO,
-       .resolution = 20833, /* 1/fs = 20.8333...us */
-       .ticks = 0x8000,
+       .resolution = 10417, /* 1 / 96 kHz = 10.41666...us */
+       .ticks = 0x10000,
        .start = snd_ymfpci_timer_start,
        .stop = snd_ymfpci_timer_stop,
        .precise_resolution = snd_ymfpci_timer_precise_resolution,