diff options
-rw-r--r-- | include/sound/asound.h | 10 | ||||
-rw-r--r-- | include/sound/pcm.h | 10 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 25 | ||||
-rw-r--r-- | sound/core/timer.c | 16 |
5 files changed, 52 insertions, 11 deletions
diff --git a/include/sound/asound.h b/include/sound/asound.h index 3ad534149c06..475eb71d65ba 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
@@ -138,7 +138,7 @@ enum { | |||
138 | * * | 138 | * * |
139 | *****************************************************************************/ | 139 | *****************************************************************************/ |
140 | 140 | ||
141 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) | 141 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) |
142 | 142 | ||
143 | typedef unsigned long snd_pcm_uframes_t; | 143 | typedef unsigned long snd_pcm_uframes_t; |
144 | typedef signed long snd_pcm_sframes_t; | 144 | typedef signed long snd_pcm_sframes_t; |
@@ -435,9 +435,15 @@ struct snd_xfern { | |||
435 | }; | 435 | }; |
436 | 436 | ||
437 | enum { | 437 | enum { |
438 | SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ | ||
439 | SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ | ||
440 | SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, | ||
441 | }; | ||
442 | |||
443 | enum { | ||
438 | SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int), | 444 | SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int), |
439 | SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info), | 445 | SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info), |
440 | SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int), | 446 | SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int), |
441 | SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params), | 447 | SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params), |
442 | SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params), | 448 | SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params), |
443 | SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12), | 449 | SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12), |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 5e9cc460075e..65f636223d39 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -323,6 +323,7 @@ struct snd_pcm_runtime { | |||
323 | 323 | ||
324 | /* -- timer -- */ | 324 | /* -- timer -- */ |
325 | unsigned int timer_resolution; /* timer resolution */ | 325 | unsigned int timer_resolution; /* timer resolution */ |
326 | int tstamp_type; /* timestamp type */ | ||
326 | 327 | ||
327 | /* -- DMA -- */ | 328 | /* -- DMA -- */ |
328 | unsigned char *dma_area; /* DMA area */ | 329 | unsigned char *dma_area; /* DMA area */ |
@@ -952,6 +953,15 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); | |||
952 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); | 953 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); |
953 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); | 954 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); |
954 | 955 | ||
956 | static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime, | ||
957 | struct timespec *tv) | ||
958 | { | ||
959 | if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC) | ||
960 | do_posix_clock_monotonic_gettime(tv); | ||
961 | else | ||
962 | getnstimeofday(tv); | ||
963 | } | ||
964 | |||
955 | /* | 965 | /* |
956 | * Memory | 966 | * Memory |
957 | */ | 967 | */ |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 93d7ca502730..db3d7e934ec3 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -188,7 +188,7 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs | |||
188 | snd_pcm_sframes_t delta; | 188 | snd_pcm_sframes_t delta; |
189 | 189 | ||
190 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP) | 190 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP) |
191 | getnstimeofday((struct timespec *)&runtime->status->tstamp); | 191 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); |
192 | pos = snd_pcm_update_hw_ptr_pos(substream, runtime); | 192 | pos = snd_pcm_update_hw_ptr_pos(substream, runtime); |
193 | if (pos == SNDRV_PCM_POS_XRUN) { | 193 | if (pos == SNDRV_PCM_POS_XRUN) { |
194 | xrun(substream); | 194 | xrun(substream); |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 6245bdaffa68..cdeae7c46e3b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -598,9 +598,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
598 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP) | 598 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP) |
599 | status->tstamp = runtime->status->tstamp; | 599 | status->tstamp = runtime->status->tstamp; |
600 | else | 600 | else |
601 | getnstimeofday(&status->tstamp); | 601 | snd_pcm_gettime(runtime, &status->tstamp); |
602 | } else | 602 | } else |
603 | getnstimeofday(&status->tstamp); | 603 | snd_pcm_gettime(runtime, &status->tstamp); |
604 | status->appl_ptr = runtime->control->appl_ptr; | 604 | status->appl_ptr = runtime->control->appl_ptr; |
605 | status->hw_ptr = runtime->status->hw_ptr; | 605 | status->hw_ptr = runtime->status->hw_ptr; |
606 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 606 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -688,7 +688,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream) | |||
688 | if (runtime->trigger_master == NULL) | 688 | if (runtime->trigger_master == NULL) |
689 | return; | 689 | return; |
690 | if (runtime->trigger_master == substream) { | 690 | if (runtime->trigger_master == substream) { |
691 | getnstimeofday(&runtime->trigger_tstamp); | 691 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); |
692 | } else { | 692 | } else { |
693 | snd_pcm_trigger_tstamp(runtime->trigger_master); | 693 | snd_pcm_trigger_tstamp(runtime->trigger_master); |
694 | runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; | 694 | runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; |
@@ -2519,6 +2519,21 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, | |||
2519 | return -EFAULT; | 2519 | return -EFAULT; |
2520 | return 0; | 2520 | return 0; |
2521 | } | 2521 | } |
2522 | |||
2523 | static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg) | ||
2524 | { | ||
2525 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2526 | int arg; | ||
2527 | |||
2528 | if (get_user(arg, _arg)) | ||
2529 | return -EFAULT; | ||
2530 | if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST) | ||
2531 | return -EINVAL; | ||
2532 | runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY; | ||
2533 | if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC) | ||
2534 | runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; | ||
2535 | return 0; | ||
2536 | } | ||
2522 | 2537 | ||
2523 | static int snd_pcm_common_ioctl1(struct file *file, | 2538 | static int snd_pcm_common_ioctl1(struct file *file, |
2524 | struct snd_pcm_substream *substream, | 2539 | struct snd_pcm_substream *substream, |
@@ -2531,8 +2546,8 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2531 | return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; | 2546 | return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; |
2532 | case SNDRV_PCM_IOCTL_INFO: | 2547 | case SNDRV_PCM_IOCTL_INFO: |
2533 | return snd_pcm_info_user(substream, arg); | 2548 | return snd_pcm_info_user(substream, arg); |
2534 | case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */ | 2549 | case SNDRV_PCM_IOCTL_TTSTAMP: |
2535 | return 0; | 2550 | return snd_pcm_tstamp(substream, arg); |
2536 | case SNDRV_PCM_IOCTL_HW_REFINE: | 2551 | case SNDRV_PCM_IOCTL_HW_REFINE: |
2537 | return snd_pcm_hw_refine_user(substream, arg); | 2552 | return snd_pcm_hw_refine_user(substream, arg); |
2538 | case SNDRV_PCM_IOCTL_HW_PARAMS: | 2553 | case SNDRV_PCM_IOCTL_HW_PARAMS: |
diff --git a/sound/core/timer.c b/sound/core/timer.c index e7dc56ca4b97..7e5fe2d91662 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -44,11 +44,14 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | static int timer_limit = DEFAULT_TIMER_LIMIT; | 46 | static int timer_limit = DEFAULT_TIMER_LIMIT; |
47 | static int timer_tstamp_monotonic = 1; | ||
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); | 48 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); |
48 | MODULE_DESCRIPTION("ALSA timer interface"); | 49 | MODULE_DESCRIPTION("ALSA timer interface"); |
49 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
50 | module_param(timer_limit, int, 0444); | 51 | module_param(timer_limit, int, 0444); |
51 | MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); | 52 | MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); |
53 | module_param(timer_tstamp_monotonic, int, 0444); | ||
54 | MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default)."); | ||
52 | 55 | ||
53 | struct snd_timer_user { | 56 | struct snd_timer_user { |
54 | struct snd_timer_instance *timeri; | 57 | struct snd_timer_instance *timeri; |
@@ -381,7 +384,10 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
381 | struct snd_timer_instance *ts; | 384 | struct snd_timer_instance *ts; |
382 | struct timespec tstamp; | 385 | struct timespec tstamp; |
383 | 386 | ||
384 | getnstimeofday(&tstamp); | 387 | if (timer_tstamp_monotonic) |
388 | do_posix_clock_monotonic_gettime(&tstamp); | ||
389 | else | ||
390 | getnstimeofday(&tstamp); | ||
385 | snd_assert(event >= SNDRV_TIMER_EVENT_START && | 391 | snd_assert(event >= SNDRV_TIMER_EVENT_START && |
386 | event <= SNDRV_TIMER_EVENT_PAUSE, return); | 392 | event <= SNDRV_TIMER_EVENT_PAUSE, return); |
387 | if (event == SNDRV_TIMER_EVENT_START || | 393 | if (event == SNDRV_TIMER_EVENT_START || |
@@ -1182,8 +1188,12 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, | |||
1182 | spin_unlock(&tu->qlock); | 1188 | spin_unlock(&tu->qlock); |
1183 | return; | 1189 | return; |
1184 | } | 1190 | } |
1185 | if (tu->last_resolution != resolution || ticks > 0) | 1191 | if (tu->last_resolution != resolution || ticks > 0) { |
1186 | getnstimeofday(&tstamp); | 1192 | if (timer_tstamp_monotonic) |
1193 | do_posix_clock_monotonic_gettime(&tstamp); | ||
1194 | else | ||
1195 | getnstimeofday(&tstamp); | ||
1196 | } | ||
1187 | if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && | 1197 | if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && |
1188 | tu->last_resolution != resolution) { | 1198 | tu->last_resolution != resolution) { |
1189 | r1.event = SNDRV_TIMER_EVENT_RESOLUTION; | 1199 | r1.event = SNDRV_TIMER_EVENT_RESOLUTION; |