diff mbox

[RFC,28/37] ALSA: firewire-lib: enable protocol layer to handle current cycle count

Message ID 1436623968-10780-29-git-send-email-o-takashi@sakamocchi.jp (mailing list archive)
State New, archived
Headers show

Commit Message

Takashi Sakamoto July 11, 2015, 2:12 p.m. UTC
The previous commit off-loads the work to generate source packet header
to each protocol implementation. In IEC 61883-1, the source packet
header shows timestamps, thus the protocol layer needs current cycle
count.

This commit allows the protocol layer to get the cycle count.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-am824.c         |  2 ++
 sound/firewire/amdtp-stream.c        | 54 ++++++++++++++++++++++++------------
 sound/firewire/amdtp-stream.h        |  1 +
 sound/firewire/digi00x/amdtp-dot.c   |  2 ++
 sound/firewire/tascam/amdtp-tascam.c |  2 ++
 5 files changed, 44 insertions(+), 17 deletions(-)
diff mbox

Patch

diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
index 37541bd..211654b 100644
--- a/sound/firewire/amdtp-am824.c
+++ b/sound/firewire/amdtp-am824.c
@@ -360,6 +360,7 @@  EXPORT_SYMBOL(amdtp_am824_midi_trigger);
 static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycles,
 					   unsigned int *syt)
 {
 	struct amdtp_am824 *p = (struct amdtp_am824 *)s->protocol;
@@ -383,6 +384,7 @@  static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycles,
 					   unsigned int *syt)
 {
 	struct amdtp_am824 *p = (struct amdtp_am824 *)s->protocol;
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 58f6ae0..8555b84 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -403,7 +403,7 @@  static inline int queue_in_packet(struct amdtp_stream *s)
 }
 
 static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks,
-			     unsigned int syt)
+			     unsigned int cycle, unsigned int syt)
 {
 	__be32 *buffer;
 	unsigned int payload_length;
@@ -412,7 +412,8 @@  static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks,
 
 	/* CIP processing. */
 	buffer = s->buffer.packets[s->packet_index].buffer;
-	pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, &syt);
+	pcm_frames = s->process_data_blocks(s, buffer + 2, data_blocks, cycle,
+					    &syt);
 
 	buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
 				(s->data_block_quadlets << CIP_DBS_SHIFT) |
@@ -440,10 +441,11 @@  static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks,
 
 static int handle_in_packet(struct amdtp_stream *s,
 			    unsigned int payload_quadlets, __be32 *buffer,
-			    unsigned int *data_blocks)
+			    unsigned int *data_blocks, unsigned int cycle,
+			    unsigned int syt)
 {
 	u32 cip_header[2];
-	unsigned int sph, fmt, fdf, syt;
+	unsigned int sph, fmt, fdf;
 	unsigned int data_block_quadlets, data_block_counter, dbc_interval;
 	struct snd_pcm_substream *pcm;
 	unsigned int pcm_frames;
@@ -523,8 +525,8 @@  static int handle_in_packet(struct amdtp_stream *s,
 	}
 
 	/* CIP processing. */
-	syt = cip_header[1] & CIP_SYT_MASK;
-	pcm_frames = s->process_data_blocks(s, buffer + 2, *data_blocks, &syt);
+	pcm_frames = s->process_data_blocks(s, buffer + 2, *data_blocks,
+					    cycle, &syt);
 
 	if (s->flags & CIP_DBC_IS_END_EVENT)
 		s->data_block_counter = data_block_counter;
@@ -543,6 +545,18 @@  end:
 	return 0;
 }
 
+#define INCREMENT_CYCLE(cycle, addend, seconds, counts)			\
+	do {								\
+		seconds = cycle >> 13;					\
+		counts = (cycle & 0x0fff) + (addend);			\
+		if (counts >= 8000) {					\
+			counts %= 8000;					\
+			if (++seconds >= 8)				\
+				seconds %= 8;				\
+		}							\
+		cycle = (seconds << 13) | counts;			\
+	} while (0)
+
 static void out_stream_callback(struct fw_iso_context *context, u32 cycle,
 				size_t header_length, void *header,
 				void *private_data)
@@ -550,26 +564,27 @@  static void out_stream_callback(struct fw_iso_context *context, u32 cycle,
 	struct amdtp_stream *s = private_data;
 	unsigned int i, syt, packets = header_length / 4;
 	unsigned int data_blocks;
+	unsigned int seconds;
+	unsigned int counts;
 
 	if (s->packet_index < 0)
 		return;
 
-	/*
-	 * Compute the cycle of the last queued packet.
-	 * (We need only the four lowest bits for the SYT, so we can ignore
-	 * that bits 0-11 must wrap around at 3072.)
-	 */
-	cycle += QUEUE_LENGTH - packets;
+	/* Compute the cycle count for the first packet in this time. */
+	INCREMENT_CYCLE(cycle, QUEUE_LENGTH - packets + 1, seconds, counts);
 
 	for (i = 0; i < packets; ++i) {
-		syt = calculate_syt(s, ++cycle);
+		syt = calculate_syt(s, cycle);
 		data_blocks = calculate_data_blocks(s, syt);
 
-		if (handle_out_packet(s, data_blocks, syt) < 0) {
+		if (handle_out_packet(s, data_blocks, cycle, syt) < 0) {
 			s->packet_index = -1;
 			amdtp_stream_pcm_abort(s);
 			return;
 		}
+
+		/* Increment cycle count. */
+		INCREMENT_CYCLE(cycle, 1, seconds, counts);
 	}
 
 	fw_iso_context_queue_flush(s->context);
@@ -584,6 +599,8 @@  static void in_stream_callback(struct fw_iso_context *context, u32 cycle,
 	unsigned int payload_quadlets, max_payload_quadlets;
 	unsigned int data_blocks;
 	__be32 *buffer, *headers = header;
+	unsigned int seconds;
+	unsigned int counts;
 
 	if (s->packet_index < 0)
 		return;
@@ -607,22 +624,25 @@  static void in_stream_callback(struct fw_iso_context *context, u32 cycle,
 			s->packet_index = -1;
 			break;
 		}
+		syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK;
 
 		if (handle_in_packet(s, payload_quadlets, buffer,
-							&data_blocks) < 0) {
+					&data_blocks, cycle, syt) < 0) {
 			s->packet_index = -1;
 			break;
 		}
 
 		/* Process sync slave stream */
 		if (s->sync_slave && s->sync_slave->callbacked) {
-			syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK;
 			if (handle_out_packet(s->sync_slave,
-					      data_blocks, syt) < 0) {
+					data_blocks, cycle, syt) < 0) {
 				s->packet_index = -1;
 				break;
 			}
 		}
+
+		/* Increment cycle count. */
+		INCREMENT_CYCLE(cycle, 1, seconds, counts);
 	}
 
 	/* Queueing error or detecting discontinuity */
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index aa5d04d..4bcd2e4 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -126,6 +126,7 @@  struct amdtp_stream {
 	unsigned int (*process_data_blocks)(struct amdtp_stream *s,
 					    __be32 *buffer,
 					    unsigned int data_blocks,
+					    unsigned int cycle,
 					    unsigned int *syt);
 
 	/* For one PCM runtime processing. */
diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c
index 338e884..43dba43 100644
--- a/sound/firewire/digi00x/amdtp-dot.c
+++ b/sound/firewire/digi00x/amdtp-dot.c
@@ -343,6 +343,7 @@  void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
 static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycle,
 					   unsigned int *syt)
 {
 	struct amdtp_dot *p = (struct amdtp_dot *)s->protocol;
@@ -366,6 +367,7 @@  static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycle,
 					   unsigned int *syt)
 {
 	struct amdtp_dot *p = (struct amdtp_dot *)s->protocol;
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c
index ca54b85..a1a9337 100644
--- a/sound/firewire/tascam/amdtp-tascam.c
+++ b/sound/firewire/tascam/amdtp-tascam.c
@@ -172,6 +172,7 @@  static void read_control_messages(struct amdtp_stream *s,
 static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycle,
 					   unsigned int *syt)
 {
 	struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol;
@@ -189,6 +190,7 @@  static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
 static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
 					   __be32 *buffer,
 					   unsigned int data_blocks,
+					   unsigned int cycle,
 					   unsigned int *syt)
 {
 	struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol;