[alsa-devel] [PATCH RFC 06/11] ALSA: pcm: add new operation; copy_frames

Takashi Sakamoto o-takashi at sakamocchi.jp
Wed May 24 02:52:50 CEST 2017


In former commits, I introduced an alias for copy operation to PCM
frames. As a result, ALSA PCM core has wrapper functions for
driver implementation of 'struct snd_pcm_ops.silence' and
'struct snd_pcm_ops.copy'. Some helper functions in ALSA PCM core declares
that these two operations can be unified.

In this concept, this commit adds new operation; copy_frames. This is
callbacked directly without the wrappers for efficiency. Especially,
drivers for non-interleaved frames alignment can execute loop in its
own and reduce the number of function calls.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 include/sound/pcm.h  |  1 +
 sound/core/pcm_lib.c | 40 ++++++++++++++++++++++++++--------------
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 6cb8df081787..07e5469a0b55 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -82,6 +82,7 @@ struct snd_pcm_ops {
 			struct timespec *system_ts, struct timespec *audio_ts,
 			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
 			struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
+	snd_pcm_copy_frames_t copy_frames;
 	int (*copy)(struct snd_pcm_substream *substream, int channel,
 		    snd_pcm_uframes_t pos,
 		    void __user *buf, snd_pcm_uframes_t count);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 8dfe964e8931..13a0c44f5cd1 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -227,17 +227,21 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
 	if (frames == 0)
 		return;
 
-	if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
-	    runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		if (substream->ops->silence)
-			copy_frames = writei_silence;
-		else
-			copy_frames = writei_from_space1;
+	if (substream->ops->copy_frames) {
+		copy_frames = substream->ops->copy_frames;
 	} else {
-		if (substream->ops->silence)
-			copy_frames = writen_silence;
-		else
-			copy_frames = writen_from_space1;
+		if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+		    runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
+			if (substream->ops->silence)
+				copy_frames = writei_silence;
+			else
+				copy_frames = writei_from_space1;
+		} else {
+			if (substream->ops->silence)
+				copy_frames = writen_silence;
+			else
+				copy_frames = writen_from_space1;
+		}
 	}
 
 	ofs = runtime->silence_start % runtime->buffer_size;
@@ -2253,7 +2257,9 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
 	    runtime->channels > 1)
 		return -EINVAL;
 
-	if (substream->ops->copy)
+	if (substream->ops->copy_frames)
+		copy_frames = substream->ops->copy_frames;
+	else if (substream->ops->copy)
 		copy_frames = snd_pcm_lib_write_transfer;
 	else
 		copy_frames = writei_from_space1;
@@ -2314,7 +2320,9 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
 
-	if (substream->ops->copy)
+	if (substream->ops->copy_frames)
+		copy_frames = substream->ops->copy_frames;
+	else if (substream->ops->copy)
 		copy_frames = snd_pcm_lib_writev_transfer;
 	else
 		copy_frames = writen_from_space1;
@@ -2465,7 +2473,9 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
 		return -EINVAL;
 
-	if (substream->ops->copy)
+	if (substream->ops->copy_frames)
+		copy_frames = substream->ops->copy_frames;
+	else if (substream->ops->copy)
 		copy_frames = snd_pcm_lib_read_transfer;
 	else
 		copy_frames = readi_to_space1;
@@ -2523,7 +2533,9 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
 
-	if (substream->ops->copy)
+	if (substream->ops->copy_frames)
+		copy_frames = substream->ops->copy_frames;
+	else if (substream->ops->copy)
 		copy_frames = snd_pcm_lib_readv_transfer;
 	else
 		copy_frames = readn_to_space1;
-- 
2.11.0



More information about the Alsa-devel mailing list