[alsa-devel] [PATCH 2/7] ALSA: core: add .update_appl_ptr callback for pcm ops
Subhransu S. Prusty
subhransu.s.prusty at intel.com
Fri Sep 30 14:43:25 CEST 2016
From: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
When appl_ptr is updated let low-level driver know, e.g. to let the
low-level driver/hardware pre-fetch data opportunistically.
The existing .ack callback could be used but it would need to be
extended with new arguments, resulting in multiple changes in legacy
code.
Instead a new .appl_ptr_update callback is added. The difference
between .ack and .appl_ptr_update is that .ack is only called on read or
write. .appl_ptr_update is called on read, write, rewind, forward or
when updating the appl_ptr from userspace.
In the ALSA core, this capability is independent from the NO_REWIND
hardware flag. The low-level driver may however tie both options and
only use the updated appl_ptr when rewinds are disabled due to hardware
limitations.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
Signed-off-by: Babu, Ramesh <ramesh.babu at intel.com>
Signed-off-by: Vinod Koul <vinod.koul at intel.com>
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty at intel.com>
---
include/sound/pcm.h | 1 +
sound/core/pcm_lib.c | 6 ++++++
sound/core/pcm_native.c | 24 +++++++++++++++++++++++-
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 5344c16..1accb8b 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -87,6 +87,7 @@ struct snd_pcm_ops {
unsigned long offset);
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
int (*ack)(struct snd_pcm_substream *substream);
+ int (*appl_ptr_update)(struct snd_pcm_substream *substream);
};
/*
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index bb12615..1656ca9 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2090,6 +2090,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
if (substream->ops->ack)
substream->ops->ack(substream);
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
offset += frames;
size -= frames;
xfer += frames;
@@ -2322,6 +2325,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
if (substream->ops->ack)
substream->ops->ack(substream);
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
offset += frames;
size -= frames;
xfer += frames;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index be8617b..c56d4ed 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2475,6 +2475,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
appl_ptr += runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
ret = frames;
+
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
__end:
snd_pcm_stream_unlock_irq(substream);
return ret;
@@ -2526,6 +2530,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
appl_ptr += runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
ret = frames;
+
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
__end:
snd_pcm_stream_unlock_irq(substream);
return ret;
@@ -2575,6 +2583,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
ret = frames;
+
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
__end:
snd_pcm_stream_unlock_irq(substream);
return ret;
@@ -2624,6 +2636,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
ret = frames;
+
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+
__end:
snd_pcm_stream_unlock_irq(substream);
return ret;
@@ -2723,8 +2739,14 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
return err;
}
snd_pcm_stream_lock_irq(substream);
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
+ if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
+ /* boundary wrap-around is assumed to be handled in userspace */
control->appl_ptr = sync_ptr.c.control.appl_ptr;
+
+ /* let low-level driver know about appl_ptr change */
+ if (substream->ops->appl_ptr_update)
+ substream->ops->appl_ptr_update(substream);
+ }
else
sync_ptr.c.control.appl_ptr = control->appl_ptr;
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
--
1.9.1
More information about the Alsa-devel
mailing list