summaryrefslogtreecommitdiff
path: root/sound/pci/ctxfi/cthw20k1.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-06-05 18:11:07 +0400
committerTakashi Iwai <tiwai@suse.de>2009-06-05 18:44:13 +0400
commitb7bbf876087e0e2c0ba723a8398083c9a9ac1dfd (patch)
tree69a3e70658fc751ffc99eef5a6f047b19f61a4a2 /sound/pci/ctxfi/cthw20k1.c
parent6bc5874a1ddf98ac0fe6c4eab7d286c11cb1c748 (diff)
downloadlinux-b7bbf876087e0e2c0ba723a8398083c9a9ac1dfd.tar.xz
ALSA: ctxfi - Use native timer interrupt on emu20k1
emu20k1 has a native timer interrupt based on the audio clock, which is more accurate than the system timer (from the synchronization POV). This patch adds the code to handle this with multiple streams. The system timer is still used on emu20k2, and can be used also for emu20k1 easily by changing USE_SYSTEM_TIMER to 1 in cttimer.c. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ctxfi/cthw20k1.c')
-rw-r--r--sound/pci/ctxfi/cthw20k1.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index e530a6d60422..550b30a2bcf1 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -1171,6 +1171,21 @@ 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;
+}
+
/* Card hardware initialization block */
struct dac_conf {
unsigned int msr; /* master sample rate in rsrs */
@@ -1878,6 +1893,22 @@ static int uaa_to_xfi(struct pci_dev *pci)
return 0;
}
+static irqreturn_t ct_20k1_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;
@@ -1914,12 +1945,13 @@ static int hw_card_start(struct hw *hw)
hw->io_base = pci_resource_start(pci, 0);
}
- /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED,
- atc->chip_details->nm_card, hw))) {
+ err = request_irq(pci->irq, ct_20k1_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;
- */
pci_set_master(pci);
@@ -1936,6 +1968,8 @@ error1:
static int hw_card_stop(struct hw *hw)
{
/* TODO: Disable interrupt and so on... */
+ if (hw->irq >= 0)
+ synchronize_irq(hw->irq);
return 0;
}
@@ -2215,6 +2249,9 @@ int create_20k1_hw_obj(struct hw **rhw)
hw->daio_mgr_set_imapaddr = daio_mgr_set_imapaddr;
hw->daio_mgr_commit_write = daio_mgr_commit_write;
+ hw->set_timer_irq = set_timer_irq;
+ hw->set_timer_tick = set_timer_tick;
+
*rhw = hw;
return 0;