/*
* Timers abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
#include <sound/driver.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/mutex.h>
#endif
static int timer_limit = DEFAULT_TIMER_LIMIT;
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
+static int timer_tstamp_monotonic = 1;
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA timer interface");
MODULE_LICENSE("GPL");
module_param(timer_limit, int, 0444);
MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
+module_param(timer_tstamp_monotonic, int, 0444);
+MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default).");
struct snd_timer_user {
struct snd_timer_instance *timeri;
struct snd_timer_instance *ts;
struct timespec tstamp;
- getnstimeofday(&tstamp);
+ if (timer_tstamp_monotonic)
+ do_posix_clock_monotonic_gettime(&tstamp);
+ else
+ getnstimeofday(&tstamp);
snd_assert(event >= SNDRV_TIMER_EVENT_START &&
event <= SNDRV_TIMER_EVENT_PAUSE, return);
if (event == SNDRV_TIMER_EVENT_START ||
spin_unlock(&tu->qlock);
return;
}
- if (tu->last_resolution != resolution || ticks > 0)
- getnstimeofday(&tstamp);
+ if (tu->last_resolution != resolution || ticks > 0) {
+ if (timer_tstamp_monotonic)
+ do_posix_clock_monotonic_gettime(&tstamp);
+ else
+ getnstimeofday(&tstamp);
+ }
if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
tu->last_resolution != resolution) {
r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
int err = 0;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
t = tu->timeri->timer;
- snd_assert(t != NULL, return -ENXIO);
+ if (!t)
+ return -EBADFD;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
int err;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
t = tu->timeri->timer;
- snd_assert(t != NULL, return -ENXIO);
+ if (!t)
+ return -EBADFD;
if (copy_from_user(¶ms, _params, sizeof(params)))
return -EFAULT;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
struct snd_timer_status status;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
memset(&status, 0, sizeof(status));
status.tstamp = tu->tstamp;
status.resolution = snd_timer_resolution(tu->timeri);
struct snd_timer_user *tu;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
snd_timer_stop(tu->timeri);
tu->timeri->lost = 0;
tu->last_resolution = 0;
struct snd_timer_user *tu;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
}
struct snd_timer_user *tu;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
tu->timeri->lost = 0;
return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
}
struct snd_timer_user *tu;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (!tu->timeri)
+ return -EBADFD;
return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
}