summaryrefslogtreecommitdiff
path: root/sound/firewire/amdtp.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /sound/firewire/amdtp.c
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'sound/firewire/amdtp.c')
-rw-r--r--sound/firewire/amdtp.c210
1 files changed, 56 insertions, 154 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 9048777..ea995af 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -42,6 +42,9 @@ static void pcm_period_tasklet(unsigned long data);
int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
enum cip_out_flags flags)
{
+ if (flags != CIP_NONBLOCKING)
+ return -EINVAL;
+
s->unit = fw_unit_get(unit);
s->flags = flags;
s->context = ERR_PTR(-1);
@@ -59,91 +62,73 @@ EXPORT_SYMBOL(amdtp_out_stream_init);
*/
void amdtp_out_stream_destroy(struct amdtp_out_stream *s)
{
- WARN_ON(amdtp_out_stream_running(s));
+ WARN_ON(!IS_ERR(s->context));
mutex_destroy(&s->mutex);
fw_unit_put(s->unit);
}
EXPORT_SYMBOL(amdtp_out_stream_destroy);
-const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = {
- [CIP_SFC_32000] = 8,
- [CIP_SFC_44100] = 8,
- [CIP_SFC_48000] = 8,
- [CIP_SFC_88200] = 16,
- [CIP_SFC_96000] = 16,
- [CIP_SFC_176400] = 32,
- [CIP_SFC_192000] = 32,
-};
-EXPORT_SYMBOL(amdtp_syt_intervals);
-
/**
- * amdtp_out_stream_set_parameters - set stream parameters
+ * amdtp_out_stream_set_rate - set the sample rate
* @s: the AMDTP output stream to configure
* @rate: the sample rate
- * @pcm_channels: the number of PCM samples in each data block, to be encoded
- * as AM824 multi-bit linear audio
- * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
*
- * The parameters must be set before the stream is started, and must not be
+ * The sample rate must be set before the stream is started, and must not be
* changed while the stream is running.
*/
-void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s,
- unsigned int rate,
- unsigned int pcm_channels,
- unsigned int midi_ports)
+void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate)
{
- static const unsigned int rates[] = {
- [CIP_SFC_32000] = 32000,
- [CIP_SFC_44100] = 44100,
- [CIP_SFC_48000] = 48000,
- [CIP_SFC_88200] = 88200,
- [CIP_SFC_96000] = 96000,
- [CIP_SFC_176400] = 176400,
- [CIP_SFC_192000] = 192000,
+ static const struct {
+ unsigned int rate;
+ unsigned int syt_interval;
+ } rate_info[] = {
+ [CIP_SFC_32000] = { 32000, 8, },
+ [CIP_SFC_44100] = { 44100, 8, },
+ [CIP_SFC_48000] = { 48000, 8, },
+ [CIP_SFC_88200] = { 88200, 16, },
+ [CIP_SFC_96000] = { 96000, 16, },
+ [CIP_SFC_176400] = { 176400, 32, },
+ [CIP_SFC_192000] = { 192000, 32, },
};
unsigned int sfc;
- if (WARN_ON(amdtp_out_stream_running(s)))
+ if (WARN_ON(!IS_ERR(s->context)))
return;
- for (sfc = 0; sfc < CIP_SFC_COUNT; ++sfc)
- if (rates[sfc] == rate)
- goto sfc_found;
+ for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc)
+ if (rate_info[sfc].rate == rate) {
+ s->sfc = sfc;
+ s->syt_interval = rate_info[sfc].syt_interval;
+ return;
+ }
WARN_ON(1);
- return;
-
-sfc_found:
- s->dual_wire = (s->flags & CIP_HI_DUALWIRE) && sfc > CIP_SFC_96000;
- if (s->dual_wire) {
- sfc -= 2;
- rate /= 2;
- pcm_channels *= 2;
- }
- s->sfc = sfc;
- s->data_block_quadlets = pcm_channels + DIV_ROUND_UP(midi_ports, 8);
- s->pcm_channels = pcm_channels;
- s->midi_ports = midi_ports;
-
- s->syt_interval = amdtp_syt_intervals[sfc];
-
- /* default buffering in the device */
- s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
- if (s->flags & CIP_BLOCKING)
- /* additional buffering needed to adjust for no-data packets */
- s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
}
-EXPORT_SYMBOL(amdtp_out_stream_set_parameters);
+EXPORT_SYMBOL(amdtp_out_stream_set_rate);
/**
* amdtp_out_stream_get_max_payload - get the stream's packet size
* @s: the AMDTP output stream
*
* This function must not be called before the stream has been configured
- * with amdtp_out_stream_set_parameters().
+ * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
+ * amdtp_out_stream_set_midi().
*/
unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
{
- return 8 + s->syt_interval * s->data_block_quadlets * 4;
+ static const unsigned int max_data_blocks[] = {
+ [CIP_SFC_32000] = 4,
+ [CIP_SFC_44100] = 6,
+ [CIP_SFC_48000] = 6,
+ [CIP_SFC_88200] = 12,
+ [CIP_SFC_96000] = 12,
+ [CIP_SFC_176400] = 23,
+ [CIP_SFC_192000] = 24,
+ };
+
+ s->data_block_quadlets = s->pcm_channels;
+ s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
+
+ return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets;
}
EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
@@ -153,26 +138,19 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
static void amdtp_write_s32(struct amdtp_out_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames);
-static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
-static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
/**
* amdtp_out_stream_set_pcm_format - set the PCM format
* @s: the AMDTP output stream to configure
* @format: the format of the ALSA PCM device
*
- * The sample format must be set after the other paramters (rate/PCM channels/
- * MIDI) and before the stream is started, and must not be changed while the
- * stream is running.
+ * The sample format must be set before the stream is started, and must not be
+ * changed while the stream is running.
*/
void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
snd_pcm_format_t format)
{
- if (WARN_ON(amdtp_out_stream_running(s)))
+ if (WARN_ON(!IS_ERR(s->context)))
return;
switch (format) {
@@ -180,16 +158,10 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
WARN_ON(1);
/* fall through */
case SNDRV_PCM_FORMAT_S16:
- 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;
case SNDRV_PCM_FORMAT_S32:
- if (s->dual_wire)
- s->transfer_samples = amdtp_write_s32_dualwire;
- else
- s->transfer_samples = amdtp_write_s32;
+ s->transfer_samples = amdtp_write_s32;
break;
}
}
@@ -276,7 +248,7 @@ static unsigned int calculate_syt(struct amdtp_out_stream *s,
s->last_syt_offset = syt_offset;
if (syt_offset < TICKS_PER_CYCLE) {
- syt_offset += s->transfer_delay;
+ syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
syt += syt_offset % TICKS_PER_CYCLE;
@@ -296,7 +268,7 @@ static void amdtp_write_s32(struct amdtp_out_stream *s,
channels = s->pcm_channels;
src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
+ s->pcm_buffer_pointer * (runtime->frame_bits / 8);
remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
frame_step = s->data_block_quadlets - channels;
@@ -322,7 +294,7 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
channels = s->pcm_channels;
src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
+ s->pcm_buffer_pointer * (runtime->frame_bits / 8);
remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
frame_step = s->data_block_quadlets - channels;
@@ -338,68 +310,6 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
}
}
-static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
- const u32 *src;
-
- channels = s->pcm_channels;
- src = (void *)runtime->dma_area +
- s->pcm_buffer_pointer * (runtime->frame_bits / 8);
- frame_adjust_1 = channels - 1;
- frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
-
- channels /= 2;
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- *buffer = cpu_to_be32((*src >> 8) | 0x40000000);
- src++;
- buffer += 2;
- }
- buffer -= frame_adjust_1;
- for (c = 0; c < channels; ++c) {
- *buffer = cpu_to_be32((*src >> 8) | 0x40000000);
- src++;
- buffer += 2;
- }
- buffer -= frame_adjust_2;
- }
-}
-
-static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
- const u16 *src;
-
- channels = s->pcm_channels;
- src = (void *)runtime->dma_area +
- s->pcm_buffer_pointer * (runtime->frame_bits / 8);
- frame_adjust_1 = channels - 1;
- frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
-
- channels /= 2;
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- *buffer = cpu_to_be32((*src << 8) | 0x40000000);
- src++;
- buffer += 2;
- }
- buffer -= frame_adjust_1;
- for (c = 0; c < channels; ++c) {
- *buffer = cpu_to_be32((*src << 8) | 0x40000000);
- src++;
- buffer += 2;
- }
- buffer -= frame_adjust_2;
- }
-}
-
static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s,
__be32 *buffer, unsigned int frames)
{
@@ -434,14 +344,8 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
return;
index = s->packet_index;
- /* this module generate empty packet for 'no data' */
+ data_blocks = calculate_data_blocks(s);
syt = calculate_syt(s, cycle);
- if (!(s->flags & CIP_BLOCKING))
- data_blocks = calculate_data_blocks(s);
- else if (syt != 0xffff)
- data_blocks = s->syt_interval;
- else
- data_blocks = 0;
buffer = s->buffer.packets[index].buffer;
buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
@@ -482,9 +386,6 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
s->packet_index = index;
if (pcm) {
- if (s->dual_wire)
- data_blocks *= 2;
-
ptr = s->pcm_buffer_pointer + data_blocks;
if (ptr >= pcm->runtime->buffer_size)
ptr -= pcm->runtime->buffer_size;
@@ -554,8 +455,9 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s)
* @speed: firewire speed code
*
* The stream cannot be started until it has been configured with
- * amdtp_out_stream_set_parameters() and amdtp_out_stream_set_pcm_format(),
- * and it must be started before any PCM or MIDI device can be started.
+ * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
+ * amdtp_out_stream_set_midi(); and it must be started before any
+ * PCM or MIDI device can be started.
*/
int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
{
@@ -575,7 +477,7 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
mutex_lock(&s->mutex);
- if (WARN_ON(amdtp_out_stream_running(s) ||
+ if (WARN_ON(!IS_ERR(s->context) ||
(!s->pcm_channels && !s->midi_ports))) {
err = -EBADFD;
goto err_unlock;
@@ -671,7 +573,7 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s)
{
mutex_lock(&s->mutex);
- if (!amdtp_out_stream_running(s)) {
+ if (IS_ERR(s->context)) {
mutex_unlock(&s->mutex);
return;
}