diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-06-05 10:11:07 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-06-05 10:44:13 -0400 |
commit | b7bbf876087e0e2c0ba723a8398083c9a9ac1dfd (patch) | |
tree | 69a3e70658fc751ffc99eef5a6f047b19f61a4a2 /sound/pci/ctxfi/ctatc.c | |
parent | 6bc5874a1ddf98ac0fe6c4eab7d286c11cb1c748 (diff) |
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/ctatc.c')
-rw-r--r-- | sound/pci/ctxfi/ctatc.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 684947546d81..10b741977dd7 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "ctsrc.h" | 22 | #include "ctsrc.h" |
23 | #include "ctamixer.h" | 23 | #include "ctamixer.h" |
24 | #include "ctdaio.h" | 24 | #include "ctdaio.h" |
25 | #include "cttimer.h" | ||
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
27 | #include <sound/control.h> | 28 | #include <sound/control.h> |
@@ -307,6 +308,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
307 | src = apcm->src; | 308 | src = apcm->src; |
308 | } | 309 | } |
309 | 310 | ||
311 | ct_timer_prepare(apcm->timer); | ||
312 | |||
310 | return 0; | 313 | return 0; |
311 | 314 | ||
312 | error1: | 315 | error1: |
@@ -389,6 +392,7 @@ static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
389 | src->ops->set_state(src, SRC_STATE_INIT); | 392 | src->ops->set_state(src, SRC_STATE_INIT); |
390 | src->ops->commit_write(src); | 393 | src->ops->commit_write(src); |
391 | 394 | ||
395 | ct_timer_start(apcm->timer); | ||
392 | return 0; | 396 | return 0; |
393 | } | 397 | } |
394 | 398 | ||
@@ -397,6 +401,8 @@ static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
397 | struct src *src = NULL; | 401 | struct src *src = NULL; |
398 | int i = 0; | 402 | int i = 0; |
399 | 403 | ||
404 | ct_timer_stop(apcm->timer); | ||
405 | |||
400 | src = apcm->src; | 406 | src = apcm->src; |
401 | src->ops->set_bm(src, 0); | 407 | src->ops->set_bm(src, 0); |
402 | src->ops->set_state(src, SRC_STATE_OFF); | 408 | src->ops->set_state(src, SRC_STATE_OFF); |
@@ -701,6 +707,8 @@ static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
701 | } | 707 | } |
702 | } | 708 | } |
703 | 709 | ||
710 | ct_timer_prepare(apcm->timer); | ||
711 | |||
704 | return 0; | 712 | return 0; |
705 | } | 713 | } |
706 | 714 | ||
@@ -749,6 +757,7 @@ static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
749 | /* Enable relevant SRCs synchronously */ | 757 | /* Enable relevant SRCs synchronously */ |
750 | src_mgr->commit_write(src_mgr); | 758 | src_mgr->commit_write(src_mgr); |
751 | 759 | ||
760 | ct_timer_start(apcm->timer); | ||
752 | return 0; | 761 | return 0; |
753 | } | 762 | } |
754 | 763 | ||
@@ -906,6 +915,8 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
906 | dao->ops->set_right_input(dao, &amixer->rsc); | 915 | dao->ops->set_right_input(dao, &amixer->rsc); |
907 | spin_unlock_irqrestore(&atc->atc_lock, flags); | 916 | spin_unlock_irqrestore(&atc->atc_lock, flags); |
908 | 917 | ||
918 | ct_timer_prepare(apcm->timer); | ||
919 | |||
909 | return 0; | 920 | return 0; |
910 | } | 921 | } |
911 | 922 | ||
@@ -1100,6 +1111,11 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
1100 | if (NULL == atc) | 1111 | if (NULL == atc) |
1101 | return 0; | 1112 | return 0; |
1102 | 1113 | ||
1114 | if (atc->timer) { | ||
1115 | ct_timer_free(atc->timer); | ||
1116 | atc->timer = NULL; | ||
1117 | } | ||
1118 | |||
1103 | /* Stop hardware and disable all interrupts */ | 1119 | /* Stop hardware and disable all interrupts */ |
1104 | if (NULL != atc->hw) | 1120 | if (NULL != atc->hw) |
1105 | ((struct hw *)atc->hw)->card_stop(atc->hw); | 1121 | ((struct hw *)atc->hw)->card_stop(atc->hw); |
@@ -1586,6 +1602,10 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
1586 | /* Build topology */ | 1602 | /* Build topology */ |
1587 | atc_connect_resources(atc); | 1603 | atc_connect_resources(atc); |
1588 | 1604 | ||
1605 | atc->timer = ct_timer_new(atc); | ||
1606 | if (!atc->timer) | ||
1607 | goto error1; | ||
1608 | |||
1589 | atc->create_alsa_devs = ct_create_alsa_devs; | 1609 | atc->create_alsa_devs = ct_create_alsa_devs; |
1590 | 1610 | ||
1591 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops); | 1611 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops); |
@@ -1602,4 +1622,3 @@ error1: | |||
1602 | printk(KERN_ERR "ctxfi: Something wrong!!!\n"); | 1622 | printk(KERN_ERR "ctxfi: Something wrong!!!\n"); |
1603 | return err; | 1623 | return err; |
1604 | } | 1624 | } |
1605 | |||