summaryrefslogtreecommitdiff
path: root/sound/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/amdtp-am824.c4
-rw-r--r--sound/firewire/amdtp-stream-trace.h163
-rw-r--r--sound/firewire/amdtp-stream.c536
-rw-r--r--sound/firewire/amdtp-stream.h38
-rw-r--r--sound/firewire/bebob/bebob.h5
-rw-r--r--sound/firewire/bebob/bebob_midi.c55
-rw-r--r--sound/firewire/bebob/bebob_pcm.c70
-rw-r--r--sound/firewire/bebob/bebob_stream.c362
-rw-r--r--sound/firewire/cmp.c74
-rw-r--r--sound/firewire/cmp.h7
-rw-r--r--sound/firewire/dice/Makefile2
-rw-r--r--sound/firewire/dice/dice-midi.c11
-rw-r--r--sound/firewire/dice/dice-pcm.c61
-rw-r--r--sound/firewire/dice/dice-presonus.c62
-rw-r--r--sound/firewire/dice/dice-stream.c344
-rw-r--r--sound/firewire/dice/dice.c9
-rw-r--r--sound/firewire/dice/dice.h4
-rw-r--r--sound/firewire/digi00x/amdtp-dot.c2
-rw-r--r--sound/firewire/digi00x/digi00x-midi.c11
-rw-r--r--sound/firewire/digi00x/digi00x-pcm.c64
-rw-r--r--sound/firewire/digi00x/digi00x-stream.c183
-rw-r--r--sound/firewire/digi00x/digi00x.h3
-rw-r--r--sound/firewire/fireface/ff-pcm.c56
-rw-r--r--sound/firewire/fireface/ff-protocol-former.c112
-rw-r--r--sound/firewire/fireface/ff-protocol-latter.c114
-rw-r--r--sound/firewire/fireface/ff-stream.c79
-rw-r--r--sound/firewire/fireface/ff.h2
-rw-r--r--sound/firewire/fireworks/fireworks.h6
-rw-r--r--sound/firewire/fireworks/fireworks_midi.c56
-rw-r--r--sound/firewire/fireworks/fireworks_pcm.c66
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c178
-rw-r--r--sound/firewire/motu/amdtp-motu-trace.h70
-rw-r--r--sound/firewire/motu/amdtp-motu.c10
-rw-r--r--sound/firewire/motu/motu-midi.c60
-rw-r--r--sound/firewire/motu/motu-pcm.c61
-rw-r--r--sound/firewire/motu/motu-stream.c197
-rw-r--r--sound/firewire/motu/motu.h6
-rw-r--r--sound/firewire/oxfw/oxfw-midi.c24
-rw-r--r--sound/firewire/oxfw/oxfw-pcm.c34
-rw-r--r--sound/firewire/oxfw/oxfw-stream.c351
-rw-r--r--sound/firewire/oxfw/oxfw.c17
-rw-r--r--sound/firewire/oxfw/oxfw.h22
-rw-r--r--sound/firewire/tascam/amdtp-tascam.c2
-rw-r--r--sound/firewire/tascam/tascam-pcm.c58
-rw-r--r--sound/firewire/tascam/tascam-stream.c203
-rw-r--r--sound/firewire/tascam/tascam.h1
46 files changed, 1841 insertions, 2014 deletions
diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
index 71168728940a..fd5d6b8ac557 100644
--- a/sound/firewire/amdtp-am824.c
+++ b/sound/firewire/amdtp-am824.c
@@ -82,7 +82,7 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
if (err < 0)
return err;
- s->fdf = AMDTP_FDF_AM824 | s->sfc;
+ s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
p->pcm_channels = pcm_channels;
p->midi_ports = midi_ports;
@@ -320,7 +320,7 @@ static void read_midi_messages(struct amdtp_stream *s,
u8 *b;
for (f = 0; f < frames; f++) {
- port = (8 - s->tx_first_dbc + s->data_block_counter + f) % 8;
+ port = (8 - s->ctx_data.tx.first_dbc + s->data_block_counter + f) % 8;
b = (u8 *)&buffer[p->midi_position];
len = b[0] - 0x80;
diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h
index edb5c3afa6f8..4adbbf789cbe 100644
--- a/sound/firewire/amdtp-stream-trace.h
+++ b/sound/firewire/amdtp-stream-trace.h
@@ -13,147 +13,16 @@
#include <linux/tracepoint.h>
-TRACE_EVENT(in_packet,
- TP_PROTO(const struct amdtp_stream *s, u32 cycles, u32 *cip_header, unsigned int payload_length, unsigned int index),
- TP_ARGS(s, cycles, cip_header, payload_length, index),
- TP_STRUCT__entry(
- __field(unsigned int, second)
- __field(unsigned int, cycle)
- __field(int, channel)
- __field(int, src)
- __field(int, dest)
- __field(u32, cip_header0)
- __field(u32, cip_header1)
- __field(unsigned int, payload_quadlets)
- __field(unsigned int, packet_index)
- __field(unsigned int, irq)
- __field(unsigned int, index)
- ),
- TP_fast_assign(
- __entry->second = cycles / CYCLES_PER_SECOND;
- __entry->cycle = cycles % CYCLES_PER_SECOND;
- __entry->channel = s->context->channel;
- __entry->src = fw_parent_device(s->unit)->node_id;
- __entry->dest = fw_parent_device(s->unit)->card->node_id;
- __entry->cip_header0 = cip_header[0];
- __entry->cip_header1 = cip_header[1];
- __entry->payload_quadlets = payload_length / 4;
- __entry->packet_index = s->packet_index;
- __entry->irq = !!in_interrupt();
- __entry->index = index;
- ),
- TP_printk(
- "%02u %04u %04x %04x %02d %08x %08x %03u %02u %01u %02u",
- __entry->second,
- __entry->cycle,
- __entry->src,
- __entry->dest,
- __entry->channel,
- __entry->cip_header0,
- __entry->cip_header1,
- __entry->payload_quadlets,
- __entry->packet_index,
- __entry->irq,
- __entry->index)
-);
-
-TRACE_EVENT(out_packet,
- TP_PROTO(const struct amdtp_stream *s, u32 cycles, __be32 *cip_header, unsigned int payload_length, unsigned int index),
- TP_ARGS(s, cycles, cip_header, payload_length, index),
- TP_STRUCT__entry(
- __field(unsigned int, second)
- __field(unsigned int, cycle)
- __field(int, channel)
- __field(int, src)
- __field(int, dest)
- __field(u32, cip_header0)
- __field(u32, cip_header1)
- __field(unsigned int, payload_quadlets)
- __field(unsigned int, packet_index)
- __field(unsigned int, irq)
- __field(unsigned int, index)
- ),
- TP_fast_assign(
- __entry->second = cycles / CYCLES_PER_SECOND;
- __entry->cycle = cycles % CYCLES_PER_SECOND;
- __entry->channel = s->context->channel;
- __entry->src = fw_parent_device(s->unit)->card->node_id;
- __entry->dest = fw_parent_device(s->unit)->node_id;
- __entry->cip_header0 = be32_to_cpu(cip_header[0]);
- __entry->cip_header1 = be32_to_cpu(cip_header[1]);
- __entry->payload_quadlets = payload_length / 4;
- __entry->packet_index = s->packet_index;
- __entry->irq = !!in_interrupt();
- __entry->index = index;
- ),
- TP_printk(
- "%02u %04u %04x %04x %02d %08x %08x %03u %02u %01u %02u",
- __entry->second,
- __entry->cycle,
- __entry->src,
- __entry->dest,
- __entry->channel,
- __entry->cip_header0,
- __entry->cip_header1,
- __entry->payload_quadlets,
- __entry->packet_index,
- __entry->irq,
- __entry->index)
-);
-
-TRACE_EVENT(in_packet_without_header,
- TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_quadlets, unsigned int data_blocks, unsigned int index),
- TP_ARGS(s, cycles, payload_quadlets, data_blocks, index),
- TP_STRUCT__entry(
- __field(unsigned int, second)
- __field(unsigned int, cycle)
- __field(int, channel)
- __field(int, src)
- __field(int, dest)
- __field(unsigned int, payload_quadlets)
- __field(unsigned int, data_blocks)
- __field(unsigned int, data_block_counter)
- __field(unsigned int, packet_index)
- __field(unsigned int, irq)
- __field(unsigned int, index)
- ),
- TP_fast_assign(
- __entry->second = cycles / CYCLES_PER_SECOND;
- __entry->cycle = cycles % CYCLES_PER_SECOND;
- __entry->channel = s->context->channel;
- __entry->src = fw_parent_device(s->unit)->node_id;
- __entry->dest = fw_parent_device(s->unit)->card->node_id;
- __entry->payload_quadlets = payload_quadlets;
- __entry->data_blocks = data_blocks,
- __entry->data_block_counter = s->data_block_counter,
- __entry->packet_index = s->packet_index;
- __entry->irq = !!in_interrupt();
- __entry->index = index;
- ),
- TP_printk(
- "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u",
- __entry->second,
- __entry->cycle,
- __entry->src,
- __entry->dest,
- __entry->channel,
- __entry->payload_quadlets,
- __entry->data_blocks,
- __entry->data_block_counter,
- __entry->packet_index,
- __entry->irq,
- __entry->index)
-);
-
-TRACE_EVENT(out_packet_without_header,
- TP_PROTO(const struct amdtp_stream *s, u32 cycles, unsigned int payload_length, unsigned int data_blocks, unsigned int index),
- TP_ARGS(s, cycles, payload_length, data_blocks, index),
+TRACE_EVENT(amdtp_packet,
+ TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index),
+ TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index),
TP_STRUCT__entry(
__field(unsigned int, second)
__field(unsigned int, cycle)
__field(int, channel)
__field(int, src)
__field(int, dest)
+ __dynamic_array(u8, cip_header, cip_header ? 8 : 0)
__field(unsigned int, payload_quadlets)
__field(unsigned int, data_blocks)
__field(unsigned int, data_block_counter)
@@ -165,17 +34,26 @@ TRACE_EVENT(out_packet_without_header,
__entry->second = cycles / CYCLES_PER_SECOND;
__entry->cycle = cycles % CYCLES_PER_SECOND;
__entry->channel = s->context->channel;
- __entry->src = fw_parent_device(s->unit)->card->node_id;
- __entry->dest = fw_parent_device(s->unit)->node_id;
- __entry->payload_quadlets = payload_length / 4;
- __entry->data_blocks = data_blocks,
+ if (s->direction == AMDTP_IN_STREAM) {
+ __entry->src = fw_parent_device(s->unit)->node_id;
+ __entry->dest = fw_parent_device(s->unit)->card->node_id;
+ } else {
+ __entry->src = fw_parent_device(s->unit)->card->node_id;
+ __entry->dest = fw_parent_device(s->unit)->node_id;
+ }
+ if (cip_header) {
+ memcpy(__get_dynamic_array(cip_header), cip_header,
+ __get_dynamic_array_len(cip_header));
+ }
+ __entry->payload_quadlets = payload_length / sizeof(__be32);
+ __entry->data_blocks = data_blocks;
__entry->data_block_counter = s->data_block_counter,
__entry->packet_index = s->packet_index;
__entry->irq = !!in_interrupt();
__entry->index = index;
),
TP_printk(
- "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u",
+ "%02u %04u %04x %04x %02d %03u %02u %03u %02u %01u %02u %s",
__entry->second,
__entry->cycle,
__entry->src,
@@ -186,7 +64,10 @@ TRACE_EVENT(out_packet_without_header,
__entry->data_block_counter,
__entry->packet_index,
__entry->irq,
- __entry->index)
+ __entry->index,
+ __print_array(__get_dynamic_array(cip_header),
+ __get_dynamic_array_len(cip_header),
+ sizeof(u8)))
);
#endif
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 68f5fa4b183d..4d71d74707cf 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -56,10 +56,15 @@
#define INTERRUPT_INTERVAL 16
#define QUEUE_LENGTH 48
-#define IR_HEADER_SIZE 8 // For header and timestamp.
-#define OUT_PACKET_HEADER_SIZE 0
+// For iso header, tstamp and 2 CIP header.
+#define IR_CTX_HEADER_SIZE_CIP 16
+// For iso header and tstamp.
+#define IR_CTX_HEADER_SIZE_NO_CIP 8
#define HEADER_TSTAMP_MASK 0x0000ffff
+#define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header.
+#define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing.
+
static void pcm_period_tasklet(unsigned long data);
/**
@@ -260,11 +265,18 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
s->data_block_quadlets = data_block_quadlets;
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;
+ // default buffering in the device.
+ if (s->direction == AMDTP_OUT_STREAM) {
+ s->ctx_data.rx.transfer_delay =
+ TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
+
+ if (s->flags & CIP_BLOCKING) {
+ // additional buffering needed to adjust for no-data
+ // packets.
+ s->ctx_data.rx.transfer_delay +=
+ TICKS_PER_SECOND * s->syt_interval / rate;
+ }
+ }
return 0;
}
@@ -280,15 +292,15 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters);
unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s)
{
unsigned int multiplier = 1;
- unsigned int header_size = 0;
+ unsigned int cip_header_size = 0;
if (s->flags & CIP_JUMBO_PAYLOAD)
multiplier = 5;
if (!(s->flags & CIP_NO_HEADER))
- header_size = 8;
+ cip_header_size = sizeof(__be32) * 2;
- return header_size +
- s->syt_interval * s->data_block_quadlets * 4 * multiplier;
+ return cip_header_size +
+ s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier;
}
EXPORT_SYMBOL(amdtp_stream_get_max_payload);
@@ -321,10 +333,10 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
/* Non-blocking mode. */
} else {
if (!cip_sfc_is_base_44100(s->sfc)) {
- /* Sample_rate / 8000 is an integer, and precomputed. */
- data_blocks = s->data_block_state;
+ // Sample_rate / 8000 is an integer, and precomputed.
+ data_blocks = s->ctx_data.rx.data_block_state;
} else {
- phase = s->data_block_state;
+ phase = s->ctx_data.rx.data_block_state;
/*
* This calculates the number of data blocks per packet so that
@@ -343,7 +355,7 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
data_blocks = 11 * (s->sfc >> 1) + (phase == 0);
if (++phase >= (80 >> (s->sfc >> 1)))
phase = 0;
- s->data_block_state = phase;
+ s->ctx_data.rx.data_block_state = phase;
}
}
@@ -355,9 +367,10 @@ static unsigned int calculate_syt(struct amdtp_stream *s,
{
unsigned int syt_offset, phase, index, syt;
- if (s->last_syt_offset < TICKS_PER_CYCLE) {
+ if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) {
if (!cip_sfc_is_base_44100(s->sfc))
- syt_offset = s->last_syt_offset + s->syt_offset_state;
+ syt_offset = s->ctx_data.rx.last_syt_offset +
+ s->ctx_data.rx.syt_offset_state;
else {
/*
* The time, in ticks, of the n'th SYT_INTERVAL sample is:
@@ -369,21 +382,21 @@ static unsigned int calculate_syt(struct amdtp_stream *s,
* 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
* This code generates _exactly_ the same sequence.
*/
- phase = s->syt_offset_state;
+ phase = s->ctx_data.rx.syt_offset_state;
index = phase % 13;
- syt_offset = s->last_syt_offset;
+ syt_offset = s->ctx_data.rx.last_syt_offset;
syt_offset += 1386 + ((index && !(index & 3)) ||
phase == 146);
if (++phase >= 147)
phase = 0;
- s->syt_offset_state = phase;
+ s->ctx_data.rx.syt_offset_state = phase;
}
} else
- syt_offset = s->last_syt_offset - TICKS_PER_CYCLE;
- s->last_syt_offset = syt_offset;
+ syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE;
+ s->ctx_data.rx.last_syt_offset = syt_offset;
if (syt_offset < TICKS_PER_CYCLE) {
- syt_offset += s->transfer_delay;
+ syt_offset += s->ctx_data.rx.transfer_delay;
syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
syt += syt_offset % TICKS_PER_CYCLE;
@@ -420,23 +433,15 @@ static void pcm_period_tasklet(unsigned long data)
snd_pcm_period_elapsed(pcm);
}
-static int queue_packet(struct amdtp_stream *s, unsigned int header_length,
- unsigned int payload_length)
+static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params)
{
- struct fw_iso_packet p = {0};
- int err = 0;
+ int err;
- if (IS_ERR(s->context))
- goto end;
+ params->interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL);
+ params->tag = s->tag;
+ params->sy = 0;
- p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL);
- p.tag = s->tag;
- p.header_length = header_length;
- if (payload_length > 0)
- p.payload_length = payload_length;
- else
- p.skip = true;
- err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer,
+ err = fw_iso_context_queue(s->context, params, &s->buffer.iso_buffer,
s->buffer.packets[s->packet_index].offset);
if (err < 0) {
dev_err(&s->unit->device, "queueing error: %d\n", err);
@@ -450,112 +455,83 @@ end:
}
static inline int queue_out_packet(struct amdtp_stream *s,
- unsigned int payload_length)
+ struct fw_iso_packet *params)
{
- return queue_packet(s, OUT_PACKET_HEADER_SIZE, payload_length);
+ params->skip =
+ !!(params->header_length == 0 && params->payload_length == 0);
+ return queue_packet(s, params);
}
-static inline int queue_in_packet(struct amdtp_stream *s)
+static inline int queue_in_packet(struct amdtp_stream *s,
+ struct fw_iso_packet *params)
{
- return queue_packet(s, IR_HEADER_SIZE, s->max_payload_length);
+ // Queue one packet for IR context.
+ params->header_length = s->ctx_data.tx.ctx_header_size;
+ params->payload_length = s->ctx_data.tx.max_ctx_payload_length;
+ params->skip = false;
+ return queue_packet(s, params);
}
-static int handle_out_packet(struct amdtp_stream *s,
- unsigned int payload_length, unsigned int cycle,
- unsigned int index)
+static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2],
+ unsigned int syt)
{
- __be32 *buffer;
- unsigned int syt;
- unsigned int data_blocks;
- unsigned int pcm_frames;
- struct snd_pcm_substream *pcm;
-
- buffer = s->buffer.packets[s->packet_index].buffer;
- syt = calculate_syt(s, cycle);
- data_blocks = calculate_data_blocks(s, syt);
- pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt);
-
- if (s->flags & CIP_DBC_IS_END_EVENT)
- s->data_block_counter =
- (s->data_block_counter + data_blocks) & 0xff;
-
- buffer[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) |
+ cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) |
(s->data_block_quadlets << CIP_DBS_SHIFT) |
((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) |
s->data_block_counter);
- buffer[1] = cpu_to_be32(CIP_EOH |
- ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) |
- ((s->fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) |
- (syt & CIP_SYT_MASK));
-
- if (!(s->flags & CIP_DBC_IS_END_EVENT))
- s->data_block_counter =
- (s->data_block_counter + data_blocks) & 0xff;
- payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
-
- trace_out_packet(s, cycle, buffer, payload_length, index);
-
- if (queue_out_packet(s, payload_length) < 0)
- return -EIO;
-
- pcm = READ_ONCE(s->pcm);
- if (pcm && pcm_frames > 0)
- update_pcm_pointers(s, pcm, pcm_frames);
-
- /* No need to return the number of handled data blocks. */
- return 0;
+ cip_header[1] = cpu_to_be32(CIP_EOH |
+ ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) |
+ ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) |
+ (syt & CIP_SYT_MASK));
}
-static int handle_out_packet_without_header(struct amdtp_stream *s,
- unsigned int payload_length, unsigned int cycle,
- unsigned int index)
+static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle,
+ struct fw_iso_packet *params,
+ unsigned int data_blocks, unsigned int syt,
+ unsigned int index)
{
- __be32 *buffer;
- unsigned int syt;
- unsigned int data_blocks;
- unsigned int pcm_frames;
- struct snd_pcm_substream *pcm;
-
- buffer = s->buffer.packets[s->packet_index].buffer;
- syt = calculate_syt(s, cycle);
- data_blocks = calculate_data_blocks(s, syt);
- pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt);
- s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
+ unsigned int payload_length;
+ __be32 *cip_header;
- payload_length = data_blocks * 4 * s->data_block_quadlets;
+ payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets;
+ params->payload_length = payload_length;
- trace_out_packet_without_header(s, cycle, payload_length, data_blocks,
- index);
+ if (s->flags & CIP_DBC_IS_END_EVENT) {
+ s->data_block_counter =
+ (s->data_block_counter + data_blocks) & 0xff;
+ }
- if (queue_out_packet(s, payload_length) < 0)
- return -EIO;
+ if (!(s->flags & CIP_NO_HEADER)) {
+ cip_header = (__be32 *)params->header;
+ generate_cip_header(s, cip_header, syt);
+ params->header_length = 2 * sizeof(__be32);
+ payload_length += params->header_length;
+ } else {
+ cip_header = NULL;
+ }
- pcm = READ_ONCE(s->pcm);
- if (pcm && pcm_frames > 0)
- update_pcm_pointers(s, pcm, pcm_frames);
+ trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks,
+ index);
- /* No need to return the number of handled data blocks. */
- return 0;
+ if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
+ s->data_block_counter =
+ (s->data_block_counter + data_blocks) & 0xff;
+ }
}
-static int handle_in_packet(struct amdtp_stream *s,
- unsigned int payload_length, unsigned int cycle,
- unsigned int index)
+static int check_cip_header(struct amdtp_stream *s, const __be32 *buf,
+ unsigned int payload_length,
+ unsigned int *data_blocks, unsigned int *dbc,
+ unsigned int *syt)
{
- __be32 *buffer;
u32 cip_header[2];
- unsigned int sph, fmt, fdf, syt;
- unsigned int data_block_quadlets, data_block_counter, dbc_interval;
- unsigned int data_blocks;
- struct snd_pcm_substream *pcm;
- unsigned int pcm_frames;
+ unsigned int sph;
+ unsigned int fmt;
+ unsigned int fdf;
bool lost;
- buffer = s->buffer.packets[s->packet_index].buffer;
- cip_header[0] = be32_to_cpu(buffer[0]);
- cip_header[1] = be32_to_cpu(buffer[1]);
-
- trace_in_packet(s, cycle, cip_header, payload_length, index);
+ cip_header[0] = be32_to_cpu(buf[0]);
+ cip_header[1] = be32_to_cpu(buf[1]);
/*
* This module supports 'Two-quadlet CIP header with SYT field'.
@@ -567,9 +543,7 @@ static int handle_in_packet(struct amdtp_stream *s,
dev_info_ratelimited(&s->unit->device,
"Invalid CIP header for AMDTP: %08X:%08X\n",
cip_header[0], cip_header[1]);
- data_blocks = 0;
- pcm_frames = 0;
- goto end;
+ return -EAGAIN;
}
/* Check valid protocol or not. */
@@ -579,19 +553,17 @@ static int handle_in_packet(struct amdtp_stream *s,
dev_info_ratelimited(&s->unit->device,
"Detect unexpected protocol: %08x %08x\n",
cip_header[0], cip_header[1]);
- data_blocks = 0;
- pcm_frames = 0;
- goto end;
+ return -EAGAIN;
}
/* Calculate data blocks */
fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT;
- if (payload_length < 12 ||
+ if (payload_length < sizeof(__be32) * 2 ||
(fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) {
- data_blocks = 0;
+ *data_blocks = 0;
} else {
- data_block_quadlets =
- (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT;
+ unsigned int data_block_quadlets =
+ (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT;
/* avoid division by zero */
if (data_block_quadlets == 0) {
dev_err(&s->unit->device,
@@ -602,95 +574,97 @@ static int handle_in_packet(struct amdtp_stream *s,
if (s->flags & CIP_WRONG_DBS)
data_block_quadlets = s->data_block_quadlets;
- data_blocks = (payload_length / 4 - 2) /
+ *data_blocks = (payload_length / sizeof(__be32) - 2) /
data_block_quadlets;
}
/* Check data block counter continuity */
- data_block_counter = cip_header[0] & CIP_DBC_MASK;
- if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
+ *dbc = cip_header[0] & CIP_DBC_MASK;
+ if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) &&
s->data_block_counter != UINT_MAX)
- data_block_counter = s->data_block_counter;
+ *dbc = s->data_block_counter;
if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) &&
- data_block_counter == s->tx_first_dbc) ||
+ *dbc == s->ctx_data.tx.first_dbc) ||
s->data_block_counter == UINT_MAX) {
lost = false;
} else if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
- lost = data_block_counter != s->data_block_counter;
+ lost = *dbc != s->data_block_counter;
} else {
- if (data_blocks > 0 && s->tx_dbc_interval > 0)
- dbc_interval = s->tx_dbc_interval;
+ unsigned int dbc_interval;
+
+ if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
+ dbc_interval = s->ctx_data.tx.dbc_interval;
else
- dbc_interval = data_blocks;
+ dbc_interval = *data_blocks;
- lost = data_block_counter !=
- ((s->data_block_counter + dbc_interval) & 0xff);
+ lost = *dbc != ((s->data_block_counter + dbc_interval) & 0xff);
}
if (lost) {
dev_err(&s->unit->device,
"Detect discontinuity of CIP: %02X %02X\n",
- s->data_block_counter, data_block_counter);
+ s->data_block_counter, *dbc);
return -EIO;
}
- syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK;
- pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt);
-
- if (s->flags & CIP_DBC_IS_END_EVENT)
- s->data_block_counter = data_block_counter;
- else
- s->data_block_counter =
- (data_block_counter + data_blocks) & 0xff;
-end:
- if (queue_in_packet(s) < 0)
- return -EIO;
-
- pcm = READ_ONCE(s->pcm);
- if (pcm && pcm_frames > 0)
- update_pcm_pointers(s, pcm, pcm_frames);
+ *syt = cip_header[1] & CIP_SYT_MASK;
return 0;
}
-static int handle_in_packet_without_header(struct amdtp_stream *s,
- unsigned int payload_length, unsigned int cycle,
- unsigned int index)
+static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle,
+ const __be32 *ctx_header,
+ unsigned int *payload_length,
+ unsigned int *data_blocks, unsigned int *syt,
+ unsigned int index)
{
- __be32 *buffer;
- unsigned int payload_quadlets;
- unsigned int data_blocks;
- struct snd_pcm_substream *pcm;
- unsigned int pcm_frames;
-
- buffer = s->buffer.packets[s->packet_index].buffer;
- payload_quadlets = payload_length / 4;
- data_blocks = payload_quadlets / s->data_block_quadlets;
+ unsigned int dbc;
+ const __be32 *cip_header;
+ int err;
- trace_in_packet_without_header(s, cycle, payload_quadlets, data_blocks,
- index);
+ *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
+ if (*payload_length > s->ctx_data.tx.ctx_header_size +
+ s->ctx_data.tx.max_ctx_payload_length) {
+ dev_err(&