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>
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 6849475..10b7419 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -22,6 +22,7 @@
 #include "ctsrc.h"
 #include "ctamixer.h"
 #include "ctdaio.h"
+#include "cttimer.h"
 #include <linux/delay.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
@@ -307,6 +308,8 @@
 			src = apcm->src;
 	}
 
+	ct_timer_prepare(apcm->timer);
+
 	return 0;
 
 error1:
@@ -389,6 +392,7 @@
 	src->ops->set_state(src, SRC_STATE_INIT);
 	src->ops->commit_write(src);
 
+	ct_timer_start(apcm->timer);
 	return 0;
 }
 
@@ -397,6 +401,8 @@
 	struct src *src = NULL;
 	int i = 0;
 
+	ct_timer_stop(apcm->timer);
+
 	src = apcm->src;
 	src->ops->set_bm(src, 0);
 	src->ops->set_state(src, SRC_STATE_OFF);
@@ -701,6 +707,8 @@
 		}
 	}
 
+	ct_timer_prepare(apcm->timer);
+
 	return 0;
 }
 
@@ -749,6 +757,7 @@
 	/* Enable relevant SRCs synchronously */
 	src_mgr->commit_write(src_mgr);
 
+	ct_timer_start(apcm->timer);
 	return 0;
 }
 
@@ -906,6 +915,8 @@
 	dao->ops->set_right_input(dao, &amixer->rsc);
 	spin_unlock_irqrestore(&atc->atc_lock, flags);
 
+	ct_timer_prepare(apcm->timer);
+
 	return 0;
 }
 
@@ -1100,6 +1111,11 @@
 	if (NULL == atc)
 		return 0;
 
+	if (atc->timer) {
+		ct_timer_free(atc->timer);
+		atc->timer = NULL;
+	}
+
 	/* Stop hardware and disable all interrupts */
 	if (NULL != atc->hw)
 		((struct hw *)atc->hw)->card_stop(atc->hw);
@@ -1586,6 +1602,10 @@
 	/* Build topology */
 	atc_connect_resources(atc);
 
+	atc->timer = ct_timer_new(atc);
+	if (!atc->timer)
+		goto error1;
+
 	atc->create_alsa_devs = ct_create_alsa_devs;
 
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);
@@ -1602,4 +1622,3 @@
 	printk(KERN_ERR "ctxfi: Something wrong!!!\n");
 	return err;
 }
-