aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r--sound/core/timer.c62
1 files changed, 27 insertions, 35 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 0a984e881c10..10a79aed33f8 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -88,7 +88,7 @@ static DEFINE_MUTEX(register_mutex);
88static int snd_timer_free(struct snd_timer *timer); 88static int snd_timer_free(struct snd_timer *timer);
89static int snd_timer_dev_free(struct snd_device *device); 89static int snd_timer_dev_free(struct snd_device *device);
90static int snd_timer_dev_register(struct snd_device *device); 90static int snd_timer_dev_register(struct snd_device *device);
91static int snd_timer_dev_unregister(struct snd_device *device); 91static int snd_timer_dev_disconnect(struct snd_device *device);
92 92
93static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left); 93static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left);
94 94
@@ -718,7 +718,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
718 } 718 }
719 } 719 }
720 if (timer->flags & SNDRV_TIMER_FLG_RESCHED) 720 if (timer->flags & SNDRV_TIMER_FLG_RESCHED)
721 snd_timer_reschedule(timer, ticks_left); 721 snd_timer_reschedule(timer, timer->sticks);
722 if (timer->running) { 722 if (timer->running) {
723 if (timer->hw.flags & SNDRV_TIMER_HW_STOP) { 723 if (timer->hw.flags & SNDRV_TIMER_HW_STOP) {
724 timer->hw.stop(timer); 724 timer->hw.stop(timer);
@@ -773,7 +773,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
773 static struct snd_device_ops ops = { 773 static struct snd_device_ops ops = {
774 .dev_free = snd_timer_dev_free, 774 .dev_free = snd_timer_dev_free,
775 .dev_register = snd_timer_dev_register, 775 .dev_register = snd_timer_dev_register,
776 .dev_unregister = snd_timer_dev_unregister 776 .dev_disconnect = snd_timer_dev_disconnect,
777 }; 777 };
778 778
779 snd_assert(tid != NULL, return -EINVAL); 779 snd_assert(tid != NULL, return -EINVAL);
@@ -813,6 +813,21 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
813static int snd_timer_free(struct snd_timer *timer) 813static int snd_timer_free(struct snd_timer *timer)
814{ 814{
815 snd_assert(timer != NULL, return -ENXIO); 815 snd_assert(timer != NULL, return -ENXIO);
816
817 mutex_lock(&register_mutex);
818 if (! list_empty(&timer->open_list_head)) {
819 struct list_head *p, *n;
820 struct snd_timer_instance *ti;
821 snd_printk(KERN_WARNING "timer %p is busy?\n", timer);
822 list_for_each_safe(p, n, &timer->open_list_head) {
823 list_del_init(p);
824 ti = list_entry(p, struct snd_timer_instance, open_list);
825 ti->timer = NULL;
826 }
827 }
828 list_del(&timer->device_list);
829 mutex_unlock(&register_mutex);
830
816 if (timer->private_free) 831 if (timer->private_free)
817 timer->private_free(timer); 832 timer->private_free(timer);
818 kfree(timer); 833 kfree(timer);
@@ -867,30 +882,13 @@ static int snd_timer_dev_register(struct snd_device *dev)
867 return 0; 882 return 0;
868} 883}
869 884
870static int snd_timer_unregister(struct snd_timer *timer) 885static int snd_timer_dev_disconnect(struct snd_device *device)
871{ 886{
872 struct list_head *p, *n; 887 struct snd_timer *timer = device->device_data;
873 struct snd_timer_instance *ti;
874
875 snd_assert(timer != NULL, return -ENXIO);
876 mutex_lock(&register_mutex); 888 mutex_lock(&register_mutex);
877 if (! list_empty(&timer->open_list_head)) { 889 list_del_init(&timer->device_list);
878 snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer);
879 list_for_each_safe(p, n, &timer->open_list_head) {
880 list_del_init(p);
881 ti = list_entry(p, struct snd_timer_instance, open_list);
882 ti->timer = NULL;
883 }
884 }
885 list_del(&timer->device_list);
886 mutex_unlock(&register_mutex); 890 mutex_unlock(&register_mutex);
887 return snd_timer_free(timer); 891 return 0;
888}
889
890static int snd_timer_dev_unregister(struct snd_device *device)
891{
892 struct snd_timer *timer = device->device_data;
893 return snd_timer_unregister(timer);
894} 892}
895 893
896void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp) 894void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
@@ -955,18 +953,12 @@ int snd_timer_global_register(struct snd_timer *timer)
955 return snd_timer_dev_register(&dev); 953 return snd_timer_dev_register(&dev);
956} 954}
957 955
958int snd_timer_global_unregister(struct snd_timer *timer)
959{
960 return snd_timer_unregister(timer);
961}
962
963/* 956/*
964 * System timer 957 * System timer
965 */ 958 */
966 959
967struct snd_timer_system_private { 960struct snd_timer_system_private {
968 struct timer_list tlist; 961 struct timer_list tlist;
969 struct timer * timer;
970 unsigned long last_expires; 962 unsigned long last_expires;
971 unsigned long last_jiffies; 963 unsigned long last_jiffies;
972 unsigned long correction; 964 unsigned long correction;
@@ -978,7 +970,7 @@ static void snd_timer_s_function(unsigned long data)
978 struct snd_timer_system_private *priv = timer->private_data; 970 struct snd_timer_system_private *priv = timer->private_data;
979 unsigned long jiff = jiffies; 971 unsigned long jiff = jiffies;
980 if (time_after(jiff, priv->last_expires)) 972 if (time_after(jiff, priv->last_expires))
981 priv->correction = (long)jiff - (long)priv->last_expires; 973 priv->correction += (long)jiff - (long)priv->last_expires;
982 snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies); 974 snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies);
983} 975}
984 976
@@ -994,7 +986,7 @@ static int snd_timer_s_start(struct snd_timer * timer)
994 njiff++; 986 njiff++;
995 } else { 987 } else {
996 njiff += timer->sticks - priv->correction; 988 njiff += timer->sticks - priv->correction;
997 priv->correction -= timer->sticks; 989 priv->correction = 0;
998 } 990 }
999 priv->last_expires = priv->tlist.expires = njiff; 991 priv->last_expires = priv->tlist.expires = njiff;
1000 add_timer(&priv->tlist); 992 add_timer(&priv->tlist);
@@ -1013,6 +1005,7 @@ static int snd_timer_s_stop(struct snd_timer * timer)
1013 timer->sticks = priv->last_expires - jiff; 1005 timer->sticks = priv->last_expires - jiff;
1014 else 1006 else
1015 timer->sticks = 1; 1007 timer->sticks = 1;
1008 priv->correction = 0;
1016 return 0; 1009 return 0;
1017} 1010}
1018 1011
@@ -1126,7 +1119,7 @@ static void __init snd_timer_proc_init(void)
1126 1119
1127static void __exit snd_timer_proc_done(void) 1120static void __exit snd_timer_proc_done(void)
1128{ 1121{
1129 snd_info_unregister(snd_timer_proc_entry); 1122 snd_info_free_entry(snd_timer_proc_entry);
1130} 1123}
1131#else /* !CONFIG_PROC_FS */ 1124#else /* !CONFIG_PROC_FS */
1132#define snd_timer_proc_init() 1125#define snd_timer_proc_init()
@@ -1982,7 +1975,7 @@ static void __exit alsa_timer_exit(void)
1982 /* unregister the system timer */ 1975 /* unregister the system timer */
1983 list_for_each_safe(p, n, &snd_timer_list) { 1976 list_for_each_safe(p, n, &snd_timer_list) {
1984 struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); 1977 struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
1985 snd_timer_unregister(timer); 1978 snd_timer_free(timer);
1986 } 1979 }
1987 snd_timer_proc_done(); 1980 snd_timer_proc_done();
1988#ifdef SNDRV_OSS_INFO_DEV_TIMERS 1981#ifdef SNDRV_OSS_INFO_DEV_TIMERS
@@ -2005,5 +1998,4 @@ EXPORT_SYMBOL(snd_timer_notify);
2005EXPORT_SYMBOL(snd_timer_global_new); 1998EXPORT_SYMBOL(snd_timer_global_new);
2006EXPORT_SYMBOL(snd_timer_global_free); 1999EXPORT_SYMBOL(snd_timer_global_free);
2007EXPORT_SYMBOL(snd_timer_global_register); 2000EXPORT_SYMBOL(snd_timer_global_register);
2008EXPORT_SYMBOL(snd_timer_global_unregister);
2009EXPORT_SYMBOL(snd_timer_interrupt); 2001EXPORT_SYMBOL(snd_timer_interrupt);