Commit e4e07c6c authored by Philippe Bekaert's avatar Philippe Bekaert Committed by Takashi Iwai

ALSA: hdspm: Fix single speed ADAT capture and playback with RME HDSPe AIO

By taking into account the mapping from logical to DMA channels when
enabling or disabling audio channels, ADAT channels 3 to 8 on the RME
HDSPe AIO card are now correctly captured and played back in single speed
mode.

Since the mapping is an identity mapping for all cards except AIO and
RayDAT, only those cards should be affected by this patch. It was tested on
an AIO card. The patch needs testing on other cards, in particular RayDAT.

Note: this patch does not solve ADAT capture and playback issues in double
or triple speed mode. That seems to be another problem.
Signed-off-by: default avatarPhilippe Bekaert <Philippe.Bekaert@panokkel.be>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 92bfa664
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
* *
* Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
* *
* Modified 2019-05-23 fix AIO single speed ADAT capture and playback
* by Philippe.Bekaert@uhasselt.be
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
...@@ -1105,7 +1108,7 @@ static int hdspm_autosync_ref(struct hdspm *hdspm); ...@@ -1105,7 +1108,7 @@ static int hdspm_autosync_ref(struct hdspm *hdspm);
static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out); static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
static int snd_hdspm_set_defaults(struct hdspm *hdspm); static int snd_hdspm_set_defaults(struct hdspm *hdspm);
static int hdspm_system_clock_mode(struct hdspm *hdspm); static int hdspm_system_clock_mode(struct hdspm *hdspm);
static void hdspm_set_sgbuf(struct hdspm *hdspm, static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
unsigned int reg, int channels); unsigned int reg, int channels);
...@@ -5588,11 +5591,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, ...@@ -5588,11 +5591,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut, for (i = 0; i < params_channels(params); ++i) {
params_channels(params)); int c = hdspm->channel_map_out[i];
for (i = 0; i < params_channels(params); ++i) if (c < 0)
snd_hdspm_enable_out(hdspm, i, 1); continue; /* just make sure */
hdspm_set_channel_dma_addr(hdspm, substream,
HDSPM_pageAddressBufferOut,
c);
snd_hdspm_enable_out(hdspm, c, 1);
}
hdspm->playback_buffer = hdspm->playback_buffer =
(unsigned char *) substream->runtime->dma_area; (unsigned char *) substream->runtime->dma_area;
...@@ -5600,11 +5608,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, ...@@ -5600,11 +5608,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
"Allocated sample buffer for playback at %p\n", "Allocated sample buffer for playback at %p\n",
hdspm->playback_buffer); hdspm->playback_buffer);
} else { } else {
hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, for (i = 0; i < params_channels(params); ++i) {
params_channels(params)); int c = hdspm->channel_map_in[i];
for (i = 0; i < params_channels(params); ++i) if (c < 0)
snd_hdspm_enable_in(hdspm, i, 1); continue;
hdspm_set_channel_dma_addr(hdspm, substream,
HDSPM_pageAddressBufferIn,
c);
snd_hdspm_enable_in(hdspm, c, 1);
}
hdspm->capture_buffer = hdspm->capture_buffer =
(unsigned char *) substream->runtime->dma_area; (unsigned char *) substream->runtime->dma_area;
...@@ -5665,19 +5678,17 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) ...@@ -5665,19 +5678,17 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
struct hdspm *hdspm = snd_pcm_substream_chip(substream); struct hdspm *hdspm = snd_pcm_substream_chip(substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* Just disable all channels. The saving when disabling a */
/* params_channels(params) should be enough, /* smaller set is not worth the trouble. */
but to get sure in case of error */ for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
for (i = 0; i < hdspm->max_channels_out; ++i)
snd_hdspm_enable_out(hdspm, i, 0); snd_hdspm_enable_out(hdspm, i, 0);
hdspm->playback_buffer = NULL; hdspm->playback_buffer = NULL;
} else { } else {
for (i = 0; i < hdspm->max_channels_in; ++i) for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
snd_hdspm_enable_in(hdspm, i, 0); snd_hdspm_enable_in(hdspm, i, 0);
hdspm->capture_buffer = NULL; hdspm->capture_buffer = NULL;
} }
snd_pcm_lib_free_pages(substream); snd_pcm_lib_free_pages(substream);
...@@ -6416,15 +6427,15 @@ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm) ...@@ -6416,15 +6427,15 @@ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
return 0; return 0;
} }
/* Inform the card what DMA addresses to use for the indicated channel. */
static void hdspm_set_sgbuf(struct hdspm *hdspm, /* Each channel got 16 4K pages allocated for DMA transfers. */
static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
unsigned int reg, int channels) unsigned int reg, int channel)
{ {
int i; int i;
/* continuous memory segment */ for (i = channel * 16; i < channel * 16 + 16; i++)
for (i = 0; i < (channels * 16); i++)
hdspm_write(hdspm, reg + 4 * i, hdspm_write(hdspm, reg + 4 * i,
snd_pcm_sgbuf_get_addr(substream, 4096 * i)); snd_pcm_sgbuf_get_addr(substream, 4096 * i));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment