diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-07-20 11:41:35 (GMT) |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-07-20 11:41:35 (GMT) |
commit | bc5304b6fb6c572452b538512761a126f0e0b0d8 (patch) | |
tree | 4b95742936811a8aa51c72578ef9f73a4a62310b | |
parent | 6847e154e3cd74fca6084124c097980a7634285a (diff) | |
download | linux-bc5304b6fb6c572452b538512761a126f0e0b0d8.tar.xz |
ALSA: ctxfi - Native timer support for emu20k2
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>
-rw-r--r-- | sound/pci/ctxfi/ct20k2reg.h | 9 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 55 |
2 files changed, 55 insertions, 9 deletions
diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h index 2d07986..e0394e3 100644 --- a/sound/pci/ctxfi/ct20k2reg.h +++ b/sound/pci/ctxfi/ct20k2reg.h @@ -11,9 +11,12 @@ /* 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 diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index dec46d0..0c4db2d 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -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) |