diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 5fbb79e30819..ff7e638221c5 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -300,7 +300,7 @@ typedef int __bitwise snd_pcm_subformat_t; #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ #define SNDRV_PCM_INFO_EXPLICIT_SYNC 0x10000000 /* needs explicit sync of pointers and data */ - +#define SNDRV_PCM_INFO_NO_REWINDS 0x20000000 /* hardware can only support monotonic changes of appl_ptr */ #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index fdd992772b20..f2090025236b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -2128,6 +2128,7 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr; + snd_pcm_sframes_t diff; int ret; if (old_appl_ptr == appl_ptr) @@ -2135,6 +2136,19 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, if (appl_ptr >= runtime->boundary) return -EINVAL; + /* + * check if a rewind is requested by the application + */ + if (substream->runtime->info & SNDRV_PCM_INFO_NO_REWINDS) { + diff = appl_ptr - old_appl_ptr; + if (diff >= 0) { + if (diff > runtime->buffer_size) + return -EINVAL; + } else { + if (runtime->boundary + diff > runtime->buffer_size) + return -EINVAL; + } + } runtime->control->appl_ptr = appl_ptr; if (substream->ops->ack) {