Skip to content

Commit

Permalink
ALSA: aloop: Add support for the non-interleaved access mode
Browse files Browse the repository at this point in the history
The current version of the loopback driver supports interleaved access
mode only. This patch introduces support for the non-interleaved
access mode.

When in the interleaved mode, the 'copy_play_buf' function copies data
from the playback to the capture buffer using one memcpy call. This call
copies samples for multiple, interleaved channels.

In the non-interleaved mode we have multiple channel buffers, so we have
to perform multiple memcpy calls to copy samples channel after channel.

Add new function called 'copy_play_buf_part_n', which copies a part of
each channel buffer from playback to capture. Modify the 'copy_play_buf'
to use the corresponding memory copy function(just memcpy /
copy_play_buf_part_n) depending on the access mode.

Signed-off-by: Ivan Orlov <[email protected]>
Reviewed-by: Jaroslav Kysela <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
ivanorlov2206 authored and tiwai committed Oct 6, 2023
1 parent 8eb2194 commit 4624945
Showing 1 changed file with 28 additions and 3 deletions.
31 changes: 28 additions & 3 deletions sound/drivers/aloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ struct loopback_pcm {
unsigned long last_jiffies;
/* If jiffies timer is used */
struct timer_list timer;

/* size of per channel buffer in case of non-interleaved access */
unsigned int channel_buf_n;
};

static struct platform_device *devices[SNDRV_CARDS];
Expand Down Expand Up @@ -335,7 +338,8 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
substream->runtime;
check = runtime->format != cruntime->format ||
runtime->rate != cruntime->rate ||
runtime->channels != cruntime->channels;
runtime->channels != cruntime->channels ||
runtime->access != cruntime->access;
if (!check)
return 0;
if (stream == SNDRV_PCM_STREAM_CAPTURE) {
Expand Down Expand Up @@ -472,6 +476,7 @@ static int loopback_prepare(struct snd_pcm_substream *substream)

dpcm->buf_pos = 0;
dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
dpcm->channel_buf_n = dpcm->pcm_buffer_size / runtime->channels;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
/* clear capture buffer */
dpcm->silent_size = dpcm->pcm_buffer_size;
Expand Down Expand Up @@ -522,6 +527,22 @@ static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
}
}

static void copy_play_buf_part_n(struct loopback_pcm *play, struct loopback_pcm *capt,
unsigned int size, unsigned int src_off, unsigned int dst_off)
{
unsigned int channels = capt->substream->runtime->channels;
unsigned int size_p_ch = size / channels;
unsigned int src_off_ch = src_off / channels;
unsigned int dst_off_ch = dst_off / channels;
int i;

for (i = 0; i < channels; i++) {
memcpy(capt->substream->runtime->dma_area + capt->channel_buf_n * i + dst_off_ch,
play->substream->runtime->dma_area + play->channel_buf_n * i + src_off_ch,
size_p_ch);
}
}

static void copy_play_buf(struct loopback_pcm *play,
struct loopback_pcm *capt,
unsigned int bytes)
Expand Down Expand Up @@ -556,7 +577,11 @@ static void copy_play_buf(struct loopback_pcm *play,
size = play->pcm_buffer_size - src_off;
if (dst_off + size > capt->pcm_buffer_size)
size = capt->pcm_buffer_size - dst_off;
memcpy(dst + dst_off, src + src_off, size);
if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ||
runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED)
copy_play_buf_part_n(play, capt, size, src_off, dst_off);
else
memcpy(dst + dst_off, src + src_off, size);
capt->silent_size = 0;
bytes -= size;
if (!bytes)
Expand Down Expand Up @@ -878,7 +903,7 @@ static const struct snd_pcm_hardware loopback_pcm_hardware =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME),
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NONINTERLEAVED),
.formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
Expand Down

0 comments on commit 4624945

Please sign in to comment.