return;
sfc_found:
- s->dual_wire = (s->flags & CIP_HI_DUALWIRE) && sfc > CIP_SFC_96000;
- if (s->dual_wire) {
- sfc -= 2;
- rate /= 2;
- s->pcm_channels = pcm_channels * 2;
- } else {
- s->pcm_channels = pcm_channels;
- }
+ s->pcm_channels = pcm_channels;
s->sfc = sfc;
s->data_block_quadlets = s->pcm_channels + midi_channels;
s->midi_ports = midi_ports;
static void amdtp_write_s32(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames);
-static void amdtp_write_s16_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
-static void amdtp_write_s32_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
static void amdtp_read_s32(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames);
-static void amdtp_read_s32_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
/**
* amdtp_stream_set_pcm_format - set the PCM format
/* fall through */
case SNDRV_PCM_FORMAT_S16:
if (s->direction == AMDTP_OUT_STREAM) {
- if (s->dual_wire)
- s->transfer_samples = amdtp_write_s16_dualwire;
- else
- s->transfer_samples = amdtp_write_s16;
+ s->transfer_samples = amdtp_write_s16;
break;
}
WARN_ON(1);
/* fall through */
case SNDRV_PCM_FORMAT_S32:
- if (s->direction == AMDTP_OUT_STREAM) {
- if (s->dual_wire)
- s->transfer_samples = amdtp_write_s32_dualwire;
- else
- s->transfer_samples = amdtp_write_s32;
- } else {
- if (s->dual_wire)
- s->transfer_samples = amdtp_read_s32_dualwire;
- else
- s->transfer_samples = amdtp_read_s32;
- }
+ if (s->direction == AMDTP_OUT_STREAM)
+ s->transfer_samples = amdtp_write_s32;
+ else
+ s->transfer_samples = amdtp_read_s32;
break;
}
}
}
}
-static void amdtp_write_s32_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- const u32 *src;
-
- src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
- channels = s->pcm_channels / 2;
-
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[s->pcm_positions[c] * 2] =
- cpu_to_be32((*src >> 8) | 0x40000000);
- src++;
- }
- buffer += 1;
- for (c = 0; c < channels; ++c) {
- buffer[s->pcm_positions[c] * 2] =
- cpu_to_be32((*src >> 8) | 0x40000000);
- src++;
- }
- buffer += s->data_block_quadlets - 1;
- if (--remaining_frames == 0)
- src = (void *)runtime->dma_area;
- }
-}
-
-static void amdtp_write_s16_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- const u16 *src;
-
- src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
- channels = s->pcm_channels / 2;
-
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[s->pcm_positions[c] * 2] =
- cpu_to_be32((*src << 8) | 0x40000000);
- src++;
- }
- buffer += 1;
- for (c = 0; c < channels; ++c) {
- buffer[s->pcm_positions[c] * 2] =
- cpu_to_be32((*src << 8) | 0x40000000);
- src++;
- }
- buffer += s->data_block_quadlets - 1;
- if (--remaining_frames == 0)
- src = (void *)runtime->dma_area;
- }
-}
-
static void amdtp_read_s32(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames)
}
}
-static void amdtp_read_s32_dualwire(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- u32 *dst;
-
- dst = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
- channels = s->pcm_channels / 2;
-
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- *dst =
- be32_to_cpu(buffer[s->pcm_positions[c] * 2]) << 8;
- dst++;
- }
- buffer += 1;
- for (c = 0; c < channels; ++c) {
- *dst =
- be32_to_cpu(buffer[s->pcm_positions[c] * 2]) << 8;
- dst++;
- }
- buffer += s->data_block_quadlets - 1;
- if (--remaining_frames == 0)
- dst = (void *)runtime->dma_area;
- }
-}
-
static void amdtp_fill_pcm_silence(struct amdtp_stream *s,
__be32 *buffer, unsigned int frames)
{
}
}
-static void amdtp_fill_pcm_silence_dualwire(struct amdtp_stream *s,
- __be32 *buffer, unsigned int frames)
-{
- unsigned int i, c, channels;
-
- channels = s->pcm_channels / 2;
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[s->pcm_positions[c] * 2] =
- buffer[s->pcm_positions[c] * 2 + 1] =
- cpu_to_be32(0x40000000);
- }
- buffer += s->data_block_quadlets;
- }
-}
static void amdtp_fill_midi(struct amdtp_stream *s,
__be32 *buffer, unsigned int frames)
{
unsigned int frames)
{ unsigned int ptr;
- if (s->dual_wire)
- frames *= 2;
-
ptr = s->pcm_buffer_pointer + frames;
if (ptr >= pcm->runtime->buffer_size)
ptr -= pcm->runtime->buffer_size;
pcm = ACCESS_ONCE(s->pcm);
if (pcm)
s->transfer_samples(s, pcm, buffer, data_blocks);
- else if (s->dual_wire)
- amdtp_fill_pcm_silence_dualwire(s, buffer, data_blocks);
else
amdtp_fill_pcm_silence(s, buffer, data_blocks);
if (s->midi_ports)
struct snd_pcm_hw_params *hw_params)
{
struct dice *dice = substream->private_data;
- unsigned int rate_index, mode;
+ unsigned int rate_index, mode, rate, channels, i;
int err;
mutex_lock(&dice->mutex);
if (err < 0)
return err;
- rate_index = rate_to_index(params_rate(hw_params));
+ rate = params_rate(hw_params);
+ rate_index = rate_to_index(rate);
err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
if (err < 0)
return err;
+ /*
+ * At rates above 96 kHz, pretend that the stream runs at half the
+ * actual sample rate with twice the number of channels; two samples
+ * of a channel are stored consecutively in the packet. Requires
+ * blocking mode and PCM buffer size should be aligned to SYT_INTERVAL.
+ */
+ channels = params_channels(hw_params);
+ if (rate_index > 4) {
+ if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) {
+ err = -ENOSYS;
+ return err;
+ }
+
+ for (i = 0; i < channels; i++) {
+ dice->stream.pcm_positions[i * 2] = i;
+ dice->stream.pcm_positions[i * 2 + 1] = i + channels;
+ }
+
+ rate /= 2;
+ channels *= 2;
+ }
+
mode = rate_index_to_mode(rate_index);
- amdtp_stream_set_parameters(&dice->stream,
- params_rate(hw_params),
- params_channels(hw_params),
+ amdtp_stream_set_parameters(&dice->stream, rate, channels,
dice->rx_midi_ports[mode]);
amdtp_stream_set_pcm_format(&dice->stream,
params_format(hw_params));
dice->resources.channels_mask = 0x00000000ffffffffuLL;
err = amdtp_stream_init(&dice->stream, unit, AMDTP_OUT_STREAM,
- CIP_BLOCKING | CIP_HI_DUALWIRE);
+ CIP_BLOCKING);
if (err < 0)
goto err_resources;