Commit 65845f29 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: firewire-lib/dice: add arrangements of PCM pointer and interrupts for Dice quirk

In IEC 61883-6, one data block transfers one event. In ALSA, the event equals one PCM frame,
hence one data block transfers one PCM frame. But Dice has a quirk at higher sampling rate
(176.4/192.0 kHz) that one data block transfers two PCM frames.

Commit 10550bea ("ALSA: dice/firewire-lib: Keep dualwire mode but obsolete
CIP_HI_DUALWIRE") moved some codes related to this quirk into Dice driver. But the commit
forgot to add arrangements for PCM period interrupts and DMA pointer updates. As a result, Dice
driver cannot work correctly at higher sampling rate.

This commit adds 'double_pcm_frames' parameter to amdtp structure for this quirk. When this
parameter is set, PCM period interrupts and DMA pointer updates occur at double speed than in
IEC 61883-6.
Reported-by: default avatarDaniel Robbins <drobbins@funtoo.org>
Fixes: 10550bea ("ALSA: dice/firewire-lib: Keep dualwire mode but obsolete CIP_HI_DUALWIRE")
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Cc: <stable@vger.kernel.org> # 3.16
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1033eb5b
...@@ -507,7 +507,16 @@ static void amdtp_pull_midi(struct amdtp_stream *s, ...@@ -507,7 +507,16 @@ static void amdtp_pull_midi(struct amdtp_stream *s,
static void update_pcm_pointers(struct amdtp_stream *s, static void update_pcm_pointers(struct amdtp_stream *s,
struct snd_pcm_substream *pcm, struct snd_pcm_substream *pcm,
unsigned int frames) unsigned int frames)
{ unsigned int ptr; {
unsigned int ptr;
/*
* In IEC 61883-6, one data block represents one event. In ALSA, one
* event equals to one PCM frame. But Dice has a quirk to transfer
* two PCM frames in one data block.
*/
if (s->double_pcm_frames)
frames *= 2;
ptr = s->pcm_buffer_pointer + frames; ptr = s->pcm_buffer_pointer + frames;
if (ptr >= pcm->runtime->buffer_size) if (ptr >= pcm->runtime->buffer_size)
......
...@@ -125,6 +125,7 @@ struct amdtp_stream { ...@@ -125,6 +125,7 @@ struct amdtp_stream {
unsigned int pcm_buffer_pointer; unsigned int pcm_buffer_pointer;
unsigned int pcm_period_pointer; unsigned int pcm_period_pointer;
bool pointer_flush; bool pointer_flush;
bool double_pcm_frames;
struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8]; struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
......
...@@ -567,10 +567,14 @@ static int dice_hw_params(struct snd_pcm_substream *substream, ...@@ -567,10 +567,14 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
return err; return err;
/* /*
* At rates above 96 kHz, pretend that the stream runs at half the * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
* actual sample rate with twice the number of channels; two samples * one data block of AMDTP packet. Thus sampling transfer frequency is
* of a channel are stored consecutively in the packet. Requires * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
* blocking mode and PCM buffer size should be aligned to SYT_INTERVAL. * transferred on AMDTP packets at 96 kHz. Two successive samples of a
* channel are stored consecutively in the packet. This quirk is called
* as 'Dual Wire'.
* For this quirk, blocking mode is required and PCM buffer size should
* be aligned to SYT_INTERVAL.
*/ */
channels = params_channels(hw_params); channels = params_channels(hw_params);
if (rate_index > 4) { if (rate_index > 4) {
...@@ -581,6 +585,9 @@ static int dice_hw_params(struct snd_pcm_substream *substream, ...@@ -581,6 +585,9 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
rate /= 2; rate /= 2;
channels *= 2; channels *= 2;
dice->stream.double_pcm_frames = true;
} else {
dice->stream.double_pcm_frames = false;
} }
mode = rate_index_to_mode(rate_index); mode = rate_index_to_mode(rate_index);
......
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