[alsa-devel] [PATCH RFC 08/11] ALSA: gus: an examples change for drivers which support non-interleaved buffer
Takashi Sakamoto
o-takashi at sakamocchi.jp
Wed May 24 02:52:52 CEST 2017
This is an example of new operation for copy_frames callback, in a case
of drivers for non-interleaved frame alignment.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/isa/gus/gus_pcm.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 33c1891f469a..08bc1f9931a2 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -417,6 +417,63 @@ static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
return 0;
}
+static int playback_copy_frames(struct snd_pcm_substream *substream,
+ unsigned int hwoff, unsigned long data,
+ unsigned int off, snd_pcm_uframes_t count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = pcmp->gus;
+ char __user **bufs = (char __user **)data;
+ char __user *buf;
+ unsigned int channels = runtime->channels;
+ unsigned int len = samples_to_bytes(runtime, count);
+ unsigned int bpos;
+ char *dst;
+ int w16;
+ int invert;
+ int c;
+ int err;
+
+ w16 = !!(snd_pcm_format_width(runtime->format) == 16);
+ invert = snd_pcm_format_unsigned(runtime->format);
+
+ for (c = 0; c < channels; ++c) {
+ bpos = samples_to_bytes(runtime, hwoff) +
+ c * (pcmp->dma_size / 2);
+ if (snd_BUG_ON(bpos > pcmp->dma_size))
+ return -EIO;
+ if (snd_BUG_ON(bpos + len > pcmp->dma_size))
+ return -EIO;
+ dst = runtime->dma_area + bpos;
+
+ if (bufs == NULL || bufs[c] == NULL) {
+ snd_pcm_format_set_silence(runtime->format,
+ runtime->dma_area + bpos,
+ count);
+ } else {
+ buf = bufs[c] + samples_to_bytes(runtime, off);
+
+ if (copy_from_user(runtime->dma_area + bpos, buf, len))
+ return -EFAULT;
+ }
+
+ if (len > 32) {
+ err = snd_gf1_pcm_block_change(substream, bpos,
+ pcmp->memory + bpos, len);
+ } else {
+ err = snd_gf1_pcm_poke_block(gus,
+ runtime->dma_area + bpos,
+ pcmp->memory + bpos, len, w16,
+ invert);
+ }
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
@@ -838,6 +895,7 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
.pointer = snd_gf1_pcm_playback_pointer,
.copy = snd_gf1_pcm_playback_copy,
.silence = snd_gf1_pcm_playback_silence,
+ .copy_frames = playback_copy_frames,
};
static struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
--
2.11.0
More information about the Alsa-devel
mailing list