*                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 8)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 9)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
        snd_pcm_uframes_t frames;
 };
 
+enum {
+       SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,        /* posix_clock_monotonic equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
 enum {
        SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
        SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
-       SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
+       SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int),
        SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params),
        SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params),
        SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12),
 
 
        /* -- timer -- */
        unsigned int timer_resolution;  /* timer resolution */
+       int tstamp_type;                /* timestamp type */
 
        /* -- DMA -- */           
        unsigned char *dma_area;        /* DMA area */
 void snd_pcm_timer_init(struct snd_pcm_substream *substream);
 void snd_pcm_timer_done(struct snd_pcm_substream *substream);
 
+static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
+                                  struct timespec *tv)
+{
+       if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+               do_posix_clock_monotonic_gettime(tv);
+       else
+               getnstimeofday(tv);
+}
+
 /*
  *  Memory
  */
 
        snd_pcm_sframes_t delta;
 
        if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP)
-               getnstimeofday((struct timespec *)&runtime->status->tstamp);
+               snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
        pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
        if (pos == SNDRV_PCM_POS_XRUN) {
                xrun(substream);
 
                if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP)
                        status->tstamp = runtime->status->tstamp;
                else
-                       getnstimeofday(&status->tstamp);
+                       snd_pcm_gettime(runtime, &status->tstamp);
        } else
-               getnstimeofday(&status->tstamp);
+               snd_pcm_gettime(runtime, &status->tstamp);
        status->appl_ptr = runtime->control->appl_ptr;
        status->hw_ptr = runtime->status->hw_ptr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
        if (runtime->trigger_master == NULL)
                return;
        if (runtime->trigger_master == substream) {
-               getnstimeofday(&runtime->trigger_tstamp);
+               snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
        } else {
                snd_pcm_trigger_tstamp(runtime->trigger_master);
                runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
                return -EFAULT;
        return 0;
 }
+
+static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int arg;
+       
+       if (get_user(arg, _arg))
+               return -EFAULT;
+       if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
+               return -EINVAL;
+       runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
+       if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+               runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+       return 0;
+}
                
 static int snd_pcm_common_ioctl1(struct file *file,
                                 struct snd_pcm_substream *substream,
                return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
        case SNDRV_PCM_IOCTL_INFO:
                return snd_pcm_info_user(substream, arg);
-       case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
-               return 0;
+       case SNDRV_PCM_IOCTL_TTSTAMP:
+               return snd_pcm_tstamp(substream, arg);
        case SNDRV_PCM_IOCTL_HW_REFINE:
                return snd_pcm_hw_refine_user(substream, arg);
        case SNDRV_PCM_IOCTL_HW_PARAMS:
 
 #endif
 
 static int timer_limit = DEFAULT_TIMER_LIMIT;
+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;