ALSA: ctxfi - Native timer support for emu20k2
authorTakashi Iwai <tiwai@suse.de>
Mon, 20 Jul 2009 11:41:35 +0000 (13:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Jul 2009 11:41:35 +0000 (13:41 +0200)
Added the native timer support for emu20k2, which gives much more
accurate update timing than the system timer.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/ctxfi/ct20k2reg.h
sound/pci/ctxfi/cthw20k2.c

index 2d07986f57cc4316bfda42505aa496a25d199899..e0394e3996e851dda9b6abc6d22f52d81512a3b8 100644 (file)
 
 
 /* Timer Registers */
-#define TIMER_TIMR          0x1B7004
-#define INTERRUPT_GIP       0x1B7010
-#define INTERRUPT_GIE       0x1B7014
+#define WC             0x1b7000
+#define TIMR           0x1b7004
+# define       TIMR_IE         (1<<15)
+# define       TIMR_IP         (1<<14)
+#define GIP            0x1b7010
+#define GIE            0x1b7014
 
 /* I2C Registers */
 #define I2C_IF_ADDRESS   0x1B9000
index dec46d04b041c7e33072d484f6eedd70b0f4b974..0c4db2dcab071a237743138e8e7186ee02676bbb 100644 (file)
@@ -1112,6 +1112,26 @@ static int daio_mgr_put_ctrl_blk(void *blk)
        return 0;
 }
 
+/* Timer interrupt */
+static int set_timer_irq(struct hw *hw, int enable)
+{
+       hw_write_20kx(hw, GIE, enable ? IT_INT : 0);
+       return 0;
+}
+
+static int set_timer_tick(struct hw *hw, unsigned int ticks)
+{
+       if (ticks)
+               ticks |= TIMR_IE | TIMR_IP;
+       hw_write_20kx(hw, TIMR, ticks);
+       return 0;
+}
+
+static unsigned int get_wc(struct hw *hw)
+{
+       return hw_read_20kx(hw, WC);
+}
+
 /* Card hardware initialization block */
 struct dac_conf {
        unsigned int msr; /* master sample rate in rsrs */
@@ -1841,6 +1861,22 @@ static int hw_have_digit_io_switch(struct hw *hw)
        return 0;
 }
 
+static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id)
+{
+       struct hw *hw = dev_id;
+       unsigned int status;
+
+       status = hw_read_20kx(hw, GIP);
+       if (!status)
+               return IRQ_NONE;
+
+       if (hw->irq_callback)
+               hw->irq_callback(hw->irq_callback_data, status);
+
+       hw_write_20kx(hw, GIP, status);
+       return IRQ_HANDLED;
+}
+
 static int hw_card_start(struct hw *hw)
 {
        int err = 0;
@@ -1879,12 +1915,15 @@ static int hw_card_start(struct hw *hw)
        set_field(&gctl, GCTL_UAA, 0);
        hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
 
-       /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED,
-                               atc->chip_details->nm_card, hw))) {
-               goto error3;
+       if (hw->irq < 0) {
+               err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED,
+                                 "ctxfi", hw);
+               if (err < 0) {
+                       printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
+                       goto error2;
+               }
+               hw->irq = pci->irq;
        }
-       hw->irq = pci->irq;
-       */
 
        pci_set_master(pci);
 
@@ -1972,7 +2011,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
        hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
 
        /* Reset all global pending interrupts */
-       hw_write_20kx(hw, INTERRUPT_GIE, 0);
+       hw_write_20kx(hw, GIE, 0);
        /* Reset all SRC pending interrupts */
        hw_write_20kx(hw, SRC_IP, 0);
 
@@ -2149,6 +2188,10 @@ static struct hw ct20k2_preset __devinitdata = {
        .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt,
        .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr,
        .daio_mgr_commit_write = daio_mgr_commit_write,
+
+       .set_timer_irq = set_timer_irq,
+       .set_timer_tick = set_timer_tick,
+       .get_wc = get_wc,
 };
 
 int __devinit create_20k2_hw_obj(struct hw **rhw)