alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure
@ 2020-05-08  4:36 Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 01/10] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter Takashi Sakamoto
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

Hi,

In current implementation, the packets for outgoing AMDTP streams are
processed by per-stream calculation of syt offset and the number of data
blocks per packet.

This patchset is a preparation for future extension that the packets for
outgoing AMDTP streams are processed according to the result of 'sampling
clock recovery' in IEC 61883-6:2005 from selected incoming AMDTP stream.
The preparation is to process packets for outgoing AMDTP streams by pool
in AMDTP domain structure for the sequence of syt offset and the number
of data blocks. The way to generate sequence is still the same as the
current implementation, which generates by ideal sampling transmission
frequency against IEEE 1394 bus clock.

Takashi Sakamoto (10):
  ALSA: firewire-lib: fix invalid assignment to union data for
    directional parameter
  ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI
    isoc descriptor
  ALSA: firewire-lib: add reference to domain structure from stream
    structure
  ALSA: firewire-lib: code refactoring for parameters of packet queue
    and IRQ timing
  ALSA: firewire-lib: code refactoring for syt computation
  ALSA: firewire-lib: code refactoring for syt offset calculation
  ALSA: firewire-lib: code refactoring for data block calculation
  ALSA: firewire-lib: add cache for packet sequence to AMDTP domain
    structure
  ALSA: firewire-lib: pool ideal sequence of syt offset and data block
  ALSA: firewire-lib: use sequence of syt offset and data block on pool
    in AMDTP domain

 sound/firewire/amdtp-am824.c  |   3 +-
 sound/firewire/amdtp-stream.c | 326 ++++++++++++++++++++--------------
 sound/firewire/amdtp-stream.h |  20 ++-
 3 files changed, 209 insertions(+), 140 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/10] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 02/10] ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI isoc descriptor Takashi Sakamoto
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

Although the value of FDF is used just for outgoing stream, the assignment
to union member is done for both directions of stream. At present this
causes no issue because the value of same position is reassigned later for
opposite stream. However, it's better to add if statement.

Fixes: d3d10a4a1b19 ("ALSA: firewire-lib: use union for directional parameters")
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-am824.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
index 67d735e9a6a4..fea92e148790 100644
--- a/sound/firewire/amdtp-am824.c
+++ b/sound/firewire/amdtp-am824.c
@@ -82,7 +82,8 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
 	if (err < 0)
 		return err;
 
-	s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
+	if (s->direction == AMDTP_OUT_STREAM)
+		s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
 
 	p->pcm_channels = pcm_channels;
 	p->midi_ports = midi_ports;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/10] ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI isoc descriptor
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 01/10] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 03/10] ALSA: firewire-lib: add reference to domain structure from stream structure Takashi Sakamoto
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

In descriptor of isochronous context in 1394 OHCI, the field of second
has 3 bit, thus the maximum value is 8. The value is used for correct
cycle calculation.

This commit replaces hard-coded value with macro to obsolete magic
number.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 37d38efb4c87..fcde01b54d11 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -20,6 +20,8 @@
 #define CYCLES_PER_SECOND	8000
 #define TICKS_PER_SECOND	(TICKS_PER_CYCLE * CYCLES_PER_SECOND)
 
+#define OHCI_MAX_SECOND		8
+
 /* Always support Linux tracing subsystem. */
 #define CREATE_TRACE_POINTS
 #include "amdtp-stream-trace.h"
@@ -680,8 +682,8 @@ static inline u32 compute_cycle_count(__be32 ctx_header_tstamp)
 static inline u32 increment_cycle_count(u32 cycle, unsigned int addend)
 {
 	cycle += addend;
-	if (cycle >= 8 * CYCLES_PER_SECOND)
-		cycle -= 8 * CYCLES_PER_SECOND;
+	if (cycle >= OHCI_MAX_SECOND * CYCLES_PER_SECOND)
+		cycle -= OHCI_MAX_SECOND * CYCLES_PER_SECOND;
 	return cycle;
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/10] ALSA: firewire-lib: add reference to domain structure from stream structure
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 01/10] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 02/10] ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI isoc descriptor Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 04/10] ALSA: firewire-lib: code refactoring for parameters of packet queue and IRQ timing Takashi Sakamoto
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

In current implementation, AMDTP domain structure and AMDTP stream
structure has one way of reference from the former to the latter. For
future extension, bidirectional reference is needed.

This commit adds a member into stream structure to refer to domain
structure to which the stream belongs.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 75 ++++++++++-------------------------
 sound/firewire/amdtp-stream.h |  3 ++
 2 files changed, 23 insertions(+), 55 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index fcde01b54d11..ce63ff6b7f03 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -793,14 +793,6 @@ static void process_ctx_payloads(struct amdtp_stream *s,
 		update_pcm_pointers(s, pcm, pcm_frames);
 }
 
-static void amdtp_stream_master_callback(struct fw_iso_context *context,
-					 u32 tstamp, size_t header_length,
-					 void *header, void *private_data);
-
-static void amdtp_stream_master_first_callback(struct fw_iso_context *context,
-					u32 tstamp, size_t header_length,
-					void *header, void *private_data);
-
 static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 				size_t header_length, void *header,
 				void *private_data)
@@ -810,7 +802,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 	unsigned int events_per_period = s->ctx_data.rx.events_per_period;
 	unsigned int event_count = s->ctx_data.rx.event_count;
 	unsigned int packets;
-	bool is_irq_target;
 	int i;
 
 	if (s->packet_index < 0)
@@ -823,10 +814,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 
 	process_ctx_payloads(s, s->pkt_descs, packets);
 
-	is_irq_target =
-		!!(context->callback.sc == amdtp_stream_master_callback ||
-		   context->callback.sc == amdtp_stream_master_first_callback);
-
 	for (i = 0; i < packets; ++i) {
 		const struct pkt_desc *desc = s->pkt_descs + i;
 		unsigned int syt;
@@ -845,7 +832,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 				    desc->data_blocks, desc->data_block_counter,
 				    syt, i);
 
-		if (is_irq_target) {
+		if (s == s->domain->irq_target) {
 			event_count += desc->data_blocks;
 			if (event_count >= events_per_period) {
 				event_count -= events_per_period;
@@ -898,12 +885,12 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
 	}
 }
 
-static void amdtp_stream_master_callback(struct fw_iso_context *context,
-					 u32 tstamp, size_t header_length,
-					 void *header, void *private_data)
+static void irq_target_callback(struct fw_iso_context *context, u32 tstamp,
+				size_t header_length, void *header,
+				void *private_data)
 {
-	struct amdtp_domain *d = private_data;
-	struct amdtp_stream *irq_target = d->irq_target;
+	struct amdtp_stream *irq_target = private_data;
+	struct amdtp_domain *d = irq_target->domain;
 	struct amdtp_stream *s;
 
 	out_stream_callback(context, tstamp, header_length, header, irq_target);
@@ -952,7 +939,10 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
 	} else {
 		cycle = compute_it_cycle(*ctx_header, s->queue_size);
 
-		context->callback.sc = out_stream_callback;
+		if (s == s->domain->irq_target)
+			context->callback.sc = irq_target_callback;
+		else
+			context->callback.sc = out_stream_callback;
 	}
 
 	s->start_cycle = cycle;
@@ -960,32 +950,11 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
 	context->callback.sc(context, tstamp, header_length, header, s);
 }
 
-static void amdtp_stream_master_first_callback(struct fw_iso_context *context,
-					       u32 tstamp, size_t header_length,
-					       void *header, void *private_data)
-{
-	struct amdtp_domain *d = private_data;
-	struct amdtp_stream *s = d->irq_target;
-	const __be32 *ctx_header = header;
-
-	s->callbacked = true;
-	wake_up(&s->callback_wait);
-
-	s->start_cycle = compute_it_cycle(*ctx_header, s->queue_size);
-
-	context->callback.sc = amdtp_stream_master_callback;
-
-	context->callback.sc(context, tstamp, header_length, header, d);
-}
-
 /**
  * amdtp_stream_start - start transferring packets
  * @s: the AMDTP stream to start
  * @channel: the isochronous channel on the bus
  * @speed: firewire speed code
- * @d: the AMDTP domain to which the AMDTP stream belongs
- * @is_irq_target: whether isoc context for the AMDTP stream is used to generate
- *		   hardware IRQ.
  * @start_cycle: the isochronous cycle to start the context. Start immediately
  *		 if negative value is given.
  *
@@ -994,7 +963,6 @@ static void amdtp_stream_master_first_callback(struct fw_iso_context *context,
  * device can be started.
  */
 static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
-			      struct amdtp_domain *d, bool is_irq_target,
 			      int start_cycle)
 {
 	static const struct {
@@ -1009,15 +977,14 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 		[CIP_SFC_88200]  = {  0,   67 },
 		[CIP_SFC_176400] = {  0,   67 },
 	};
-	unsigned int events_per_buffer = d->events_per_buffer;
-	unsigned int events_per_period = d->events_per_period;
+	bool is_irq_target = (s == s->domain->irq_target);
+	unsigned int events_per_buffer;
+	unsigned int events_per_period;
 	unsigned int idle_irq_interval;
 	unsigned int ctx_header_size;
 	unsigned int max_ctx_payload_size;
 	enum dma_data_direction dir;
 	int type, tag, err;
-	fw_iso_callback_t ctx_cb;
-	void *ctx_data;
 
 	mutex_lock(&s->mutex);
 
@@ -1068,6 +1035,8 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 	// This is a case that AMDTP streams in domain run just for MIDI
 	// substream. Use the number of events equivalent to 10 msec as
 	// interval of hardware IRQ.
+	events_per_buffer = s->domain->events_per_buffer;
+	events_per_period = s->domain->events_per_period;
 	if (events_per_period == 0)
 		events_per_period = amdtp_rate_table[s->sfc] / 100;
 	if (events_per_buffer == 0)
@@ -1086,16 +1055,11 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 	if (is_irq_target) {
 		s->ctx_data.rx.events_per_period = events_per_period;
 		s->ctx_data.rx.event_count = 0;
-		ctx_cb = amdtp_stream_master_first_callback;
-		ctx_data = d;
-	} else {
-		ctx_cb = amdtp_stream_first_callback;
-		ctx_data = s;
 	}
 
 	s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
 					  type, channel, speed, ctx_header_size,
-					  ctx_cb, ctx_data);
+					  amdtp_stream_first_callback, s);
 	if (IS_ERR(s->context)) {
 		err = PTR_ERR(s->context);
 		if (err == -EBUSY)
@@ -1340,6 +1304,7 @@ int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s,
 
 	s->channel = channel;
 	s->speed = speed;
+	s->domain = d;
 
 	return 0;
 }
@@ -1428,15 +1393,15 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 		}
 
 		if (s != d->irq_target) {
-			err = amdtp_stream_start(s, s->channel, s->speed, d,
-						 false, cycle_match);
+			err = amdtp_stream_start(s, s->channel, s->speed,
+						 cycle_match);
 			if (err < 0)
 				goto error;
 		}
 	}
 
 	s = d->irq_target;
-	err = amdtp_stream_start(s, s->channel, s->speed, d, true, -1);
+	err = amdtp_stream_start(s, s->channel, s->speed, -1);
 	if (err < 0)
 		goto error;
 
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index f2d44e2dc3c8..477fbfe713e5 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -108,6 +108,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)(
 						const struct pkt_desc *desc,
 						unsigned int packets,
 						struct snd_pcm_substream *pcm);
+
+struct amdtp_domain;
 struct amdtp_stream {
 	struct fw_unit *unit;
 	enum cip_flags flags;
@@ -180,6 +182,7 @@ struct amdtp_stream {
 	int channel;
 	int speed;
 	struct list_head list;
+	struct amdtp_domain *domain;
 };
 
 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/10] ALSA: firewire-lib: code refactoring for parameters of packet queue and IRQ timing
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (2 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 03/10] ALSA: firewire-lib: add reference to domain structure from stream structure Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 05/10] ALSA: firewire-lib: code refactoring for syt computation Takashi Sakamoto
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

Although the parameter for packet queue and IRQ timing is calculated when
AMDTP stream starts, the calculated parameters are the same between
streams in AMDTP domain.

This commit moves the calculation and decide the parameters when AMDTP
domain starts.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 56 ++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 27 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index ce63ff6b7f03..6130c240ff33 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -957,13 +957,16 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
  * @speed: firewire speed code
  * @start_cycle: the isochronous cycle to start the context. Start immediately
  *		 if negative value is given.
+ * @queue_size: The number of packets in the queue.
+ * @idle_irq_interval: the interval to queue packet during initial state.
  *
  * The stream cannot be started until it has been configured with
  * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI
  * device can be started.
  */
 static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
-			      int start_cycle)
+			      int start_cycle, unsigned int queue_size,
+			      unsigned int idle_irq_interval)
 {
 	static const struct {
 		unsigned int data_block;
@@ -978,9 +981,6 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 		[CIP_SFC_176400] = {  0,   67 },
 	};
 	bool is_irq_target = (s == s->domain->irq_target);
-	unsigned int events_per_buffer;
-	unsigned int events_per_period;
-	unsigned int idle_irq_interval;
 	unsigned int ctx_header_size;
 	unsigned int max_ctx_payload_size;
 	enum dma_data_direction dir;
@@ -1032,30 +1032,11 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 			max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP;
 	}
 
-	// This is a case that AMDTP streams in domain run just for MIDI
-	// substream. Use the number of events equivalent to 10 msec as
-	// interval of hardware IRQ.
-	events_per_buffer = s->domain->events_per_buffer;
-	events_per_period = s->domain->events_per_period;
-	if (events_per_period == 0)
-		events_per_period = amdtp_rate_table[s->sfc] / 100;
-	if (events_per_buffer == 0)
-		events_per_buffer = events_per_period * 3;
-
-	idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period,
-					 amdtp_rate_table[s->sfc]);
-	s->queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
-				     amdtp_rate_table[s->sfc]);
-
-	err = iso_packets_buffer_init(&s->buffer, s->unit, s->queue_size,
+	err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size,
 				      max_ctx_payload_size, dir);
 	if (err < 0)
 		goto err_unlock;
-
-	if (is_irq_target) {
-		s->ctx_data.rx.events_per_period = events_per_period;
-		s->ctx_data.rx.event_count = 0;
-	}
+	s->queue_size = queue_size;
 
 	s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
 					  type, channel, speed, ctx_header_size,
@@ -1341,6 +1322,10 @@ static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle)
  */
 int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 {
+	unsigned int events_per_buffer = d->events_per_buffer;
+	unsigned int events_per_period = d->events_per_period;
+	unsigned int idle_irq_interval;
+	unsigned int queue_size;
 	struct amdtp_stream *s;
 	int cycle;
 	int err;
@@ -1354,6 +1339,17 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 		return -ENXIO;
 	d->irq_target = s;
 
+	// This is a case that AMDTP streams in domain run just for MIDI
+	// substream. Use the number of events equivalent to 10 msec as
+	// interval of hardware IRQ.
+	if (events_per_period == 0)
+		events_per_period = amdtp_rate_table[d->irq_target->sfc] / 100;
+	if (events_per_buffer == 0)
+		events_per_buffer = events_per_period * 3;
+
+	queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
+				  amdtp_rate_table[d->irq_target->sfc]);
+
 	if (ir_delay_cycle > 0) {
 		struct fw_card *fw_card = fw_parent_device(s->unit)->card;
 
@@ -1394,14 +1390,20 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 
 		if (s != d->irq_target) {
 			err = amdtp_stream_start(s, s->channel, s->speed,
-						 cycle_match);
+						 cycle_match, queue_size, 0);
 			if (err < 0)
 				goto error;
 		}
 	}
 
 	s = d->irq_target;
-	err = amdtp_stream_start(s, s->channel, s->speed, -1);
+	s->ctx_data.rx.events_per_period = events_per_period;
+	s->ctx_data.rx.event_count = 0;
+
+	idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period,
+					 amdtp_rate_table[d->irq_target->sfc]);
+	err = amdtp_stream_start(s, s->channel, s->speed, -1, queue_size,
+				 idle_irq_interval);
 	if (err < 0)
 		goto error;
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/10] ALSA: firewire-lib: code refactoring for syt computation
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (3 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 04/10] ALSA: firewire-lib: code refactoring for parameters of packet queue and IRQ timing Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 06/10] ALSA: firewire-lib: code refactoring for syt offset calculation Takashi Sakamoto
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

In current implementation for outgoing AMDTP packet, the value of syt
field in CIP header is computed when calculating syt offset. For
future extension, it's convenient to split the computation and
calculation.

This commit splits them.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 36 +++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 6130c240ff33..1605ea4301ce 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -383,10 +383,9 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
 	return data_blocks;
 }
 
-static unsigned int calculate_syt(struct amdtp_stream *s,
-				  unsigned int cycle)
+static unsigned int calculate_syt_offset(struct amdtp_stream *s)
 {
-	unsigned int syt_offset, phase, index, syt;
+	unsigned int syt_offset, phase, index;
 
 	if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) {
 		if (!cip_sfc_is_base_44100(s->sfc))
@@ -416,15 +415,10 @@ static unsigned int calculate_syt(struct amdtp_stream *s,
 		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->ctx_data.rx.transfer_delay;
-		syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
-		syt += syt_offset % TICKS_PER_CYCLE;
+	if (syt_offset >= TICKS_PER_CYCLE)
+		syt_offset = CIP_SYT_NO_INFO;
 
-		return syt & CIP_SYT_MASK;
-	} else {
-		return CIP_SYT_NO_INFO;
-	}
+	return syt_offset;
 }
 
 static void update_pcm_pointers(struct amdtp_stream *s,
@@ -740,6 +734,17 @@ static int generate_device_pkt_descs(struct amdtp_stream *s,
 	return 0;
 }
 
+static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle,
+				unsigned int transfer_delay)
+{
+	unsigned int syt;
+
+	syt_offset += transfer_delay;
+	syt = ((cycle + syt_offset / TICKS_PER_CYCLE) << 12) |
+	      (syt_offset % TICKS_PER_CYCLE);
+	return syt & CIP_SYT_MASK;
+}
+
 static void generate_ideal_pkt_descs(struct amdtp_stream *s,
 				     struct pkt_desc *descs,
 				     const __be32 *ctx_header,
@@ -751,9 +756,16 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s,
 	for (i = 0; i < packets; ++i) {
 		struct pkt_desc *desc = descs + i;
 		unsigned int index = (s->packet_index + i) % s->queue_size;
+		unsigned int syt_offset;
 
 		desc->cycle = compute_it_cycle(*ctx_header, s->queue_size);
-		desc->syt = calculate_syt(s, desc->cycle);
+		syt_offset = calculate_syt_offset(s);
+		if (syt_offset != CIP_SYT_NO_INFO) {
+			desc->syt = compute_syt(syt_offset, desc->cycle,
+						s->ctx_data.rx.transfer_delay);
+		} else {
+			desc->syt = syt_offset;
+		}
 		desc->data_blocks = calculate_data_blocks(s, desc->syt);
 
 		if (s->flags & CIP_DBC_IS_END_EVENT)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/10] ALSA: firewire-lib: code refactoring for syt offset calculation
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (4 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 05/10] ALSA: firewire-lib: code refactoring for syt computation Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 07/10] ALSA: firewire-lib: code refactoring for data block calculation Takashi Sakamoto
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

When calculating syt offset, some states are stored in AMDTP stream
structure. This is inconvenient when reuse the calculation from
non-stream structure.

This commit applies refactoring to helper function for the calculation
so that the function doesn't touch AMDTP stream structure.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 1605ea4301ce..9041510cb6aa 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -383,14 +383,14 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
 	return data_blocks;
 }
 
-static unsigned int calculate_syt_offset(struct amdtp_stream *s)
+static unsigned int calculate_syt_offset(unsigned int *last_syt_offset,
+			unsigned int *syt_offset_state, enum cip_sfc sfc)
 {
-	unsigned int syt_offset, phase, index;
+	unsigned int syt_offset;
 
-	if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) {
-		if (!cip_sfc_is_base_44100(s->sfc))
-			syt_offset = s->ctx_data.rx.last_syt_offset +
-				     s->ctx_data.rx.syt_offset_state;
+	if (*last_syt_offset < TICKS_PER_CYCLE) {
+		if (!cip_sfc_is_base_44100(sfc))
+			syt_offset = *last_syt_offset + *syt_offset_state;
 		else {
 		/*
 		 * The time, in ticks, of the n'th SYT_INTERVAL sample is:
@@ -402,18 +402,19 @@ static unsigned int calculate_syt_offset(struct amdtp_stream *s)
 		 *   1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
 		 * This code generates _exactly_ the same sequence.
 		 */
-			phase = s->ctx_data.rx.syt_offset_state;
-			index = phase % 13;
-			syt_offset = s->ctx_data.rx.last_syt_offset;
+			unsigned int phase = *syt_offset_state;
+			unsigned int index = phase % 13;
+
+			syt_offset = *last_syt_offset;
 			syt_offset += 1386 + ((index && !(index & 3)) ||
 					      phase == 146);
 			if (++phase >= 147)
 				phase = 0;
-			s->ctx_data.rx.syt_offset_state = phase;
+			*syt_offset_state = phase;
 		}
 	} else
-		syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE;
-	s->ctx_data.rx.last_syt_offset = syt_offset;
+		syt_offset = *last_syt_offset - TICKS_PER_CYCLE;
+	*last_syt_offset = syt_offset;
 
 	if (syt_offset >= TICKS_PER_CYCLE)
 		syt_offset = CIP_SYT_NO_INFO;
@@ -759,7 +760,9 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s,
 		unsigned int syt_offset;
 
 		desc->cycle = compute_it_cycle(*ctx_header, s->queue_size);
-		syt_offset = calculate_syt_offset(s);
+		syt_offset = calculate_syt_offset(
+				&s->ctx_data.rx.last_syt_offset,
+				&s->ctx_data.rx.syt_offset_state, s->sfc);
 		if (syt_offset != CIP_SYT_NO_INFO) {
 			desc->syt = compute_syt(syt_offset, desc->cycle,
 						s->ctx_data.rx.transfer_delay);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/10] ALSA: firewire-lib: code refactoring for data block calculation
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (5 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 06/10] ALSA: firewire-lib: code refactoring for syt offset calculation Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 08/10] ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure Takashi Sakamoto
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

When calculating the number of data blocks per packet, some states are
stored in AMDTP stream structure. This is inconvenient when reuse the
calculation from non-stream structure.

This commit applies refactoring to helper function for the calculation
so that the function doesn't touch AMDTP stream structure.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 9041510cb6aa..efd1f2a40cf1 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -339,25 +339,26 @@ void amdtp_stream_pcm_prepare(struct amdtp_stream *s)
 }
 EXPORT_SYMBOL(amdtp_stream_pcm_prepare);
 
-static unsigned int calculate_data_blocks(struct amdtp_stream *s,
-					  unsigned int syt)
+static unsigned int calculate_data_blocks(unsigned int *data_block_state,
+				bool is_blocking, bool is_no_info,
+				unsigned int syt_interval, enum cip_sfc sfc)
 {
-	unsigned int phase, data_blocks;
+	unsigned int data_blocks;
 
 	/* Blocking mode. */
-	if (s->flags & CIP_BLOCKING) {
+	if (is_blocking) {
 		/* This module generate empty packet for 'no data'. */
-		if (syt == CIP_SYT_NO_INFO)
+		if (is_no_info)
 			data_blocks = 0;
 		else
-			data_blocks = s->syt_interval;
+			data_blocks = syt_interval;
 	/* Non-blocking mode. */
 	} else {
-		if (!cip_sfc_is_base_44100(s->sfc)) {
+		if (!cip_sfc_is_base_44100(sfc)) {
 			// Sample_rate / 8000 is an integer, and precomputed.
-			data_blocks = s->ctx_data.rx.data_block_state;
+			data_blocks = *data_block_state;
 		} else {
-			phase = s->ctx_data.rx.data_block_state;
+			unsigned int phase = *data_block_state;
 
 		/*
 		 * This calculates the number of data blocks per packet so that
@@ -367,16 +368,16 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
 		 *    as possible in the sequence (to prevent underruns of the
 		 *    device's buffer).
 		 */
-			if (s->sfc == CIP_SFC_44100)
+			if (sfc == CIP_SFC_44100)
 				/* 6 6 5 6 5 6 5 ... */
 				data_blocks = 5 + ((phase & 1) ^
 						   (phase == 0 || phase >= 40));
 			else
 				/* 12 11 11 11 11 ... or 23 22 22 22 22 ... */
-				data_blocks = 11 * (s->sfc >> 1) + (phase == 0);
-			if (++phase >= (80 >> (s->sfc >> 1)))
+				data_blocks = 11 * (sfc >> 1) + (phase == 0);
+			if (++phase >= (80 >> (sfc >> 1)))
 				phase = 0;
-			s->ctx_data.rx.data_block_state = phase;
+			*data_block_state = phase;
 		}
 	}
 
@@ -769,7 +770,11 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s,
 		} else {
 			desc->syt = syt_offset;
 		}
-		desc->data_blocks = calculate_data_blocks(s, desc->syt);
+		desc->data_blocks =
+			calculate_data_blocks(&s->ctx_data.rx.data_block_state,
+					      !!(s->flags & CIP_BLOCKING),
+					      desc->syt == CIP_SYT_NO_INFO,
+					      s->syt_interval, s->sfc);
 
 		if (s->flags & CIP_DBC_IS_END_EVENT)
 			dbc = (dbc + desc->data_blocks) & 0xff;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/10] ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (6 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 07/10] ALSA: firewire-lib: code refactoring for data block calculation Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 09/10] ALSA: firewire-lib: pool ideal sequence of syt offset and data block Takashi Sakamoto
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

For future extension, storage is required to store packet sequence in
incoming AMDTP stream to recover media clock for outgoing AMDTP stream.

This commit adds the storage to AMDTP domain for this purpose. The
packet sequence is represented by 'struct seq_desc' which has two
members; syt_offset and the number of data blocks. The size of storage
is decided according to the size of packet queue.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 15 ++++++++++++++-
 sound/firewire/amdtp-stream.h |  9 +++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index efd1f2a40cf1..f1c8611cfc70 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -1269,6 +1269,8 @@ int amdtp_domain_init(struct amdtp_domain *d)
 
 	d->events_per_period = 0;
 
+	d->seq_descs = NULL;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_init);
@@ -1370,12 +1372,18 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 	queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
 				  amdtp_rate_table[d->irq_target->sfc]);
 
+	d->seq_descs = kcalloc(queue_size, sizeof(*d->seq_descs), GFP_KERNEL);
+	if (!d->seq_descs)
+		return -ENOMEM;
+	d->seq_size = queue_size;
+	d->seq_tail = 0;
+
 	if (ir_delay_cycle > 0) {
 		struct fw_card *fw_card = fw_parent_device(s->unit)->card;
 
 		err = get_current_cycle_time(fw_card, &cycle);
 		if (err < 0)
-			return err;
+			goto error;
 
 		// No need to care overflow in cycle field because of enough
 		// width.
@@ -1431,6 +1439,8 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 error:
 	list_for_each_entry(s, &d->streams, list)
 		amdtp_stream_stop(s);
+	kfree(d->seq_descs);
+	d->seq_descs = NULL;
 	return err;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_start);
@@ -1455,5 +1465,8 @@ void amdtp_domain_stop(struct amdtp_domain *d)
 
 	d->events_per_period = 0;
 	d->irq_target = NULL;
+
+	kfree(d->seq_descs);
+	d->seq_descs = NULL;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_stop);
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index 477fbfe713e5..84a01efa5a85 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -276,6 +276,11 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
 				  msecs_to_jiffies(timeout)) > 0;
 }
 
+struct seq_desc {
+	unsigned int syt_offset;
+	unsigned int data_blocks;
+};
+
 struct amdtp_domain {
 	struct list_head streams;
 
@@ -283,6 +288,10 @@ struct amdtp_domain {
 	unsigned int events_per_buffer;
 
 	struct amdtp_stream *irq_target;
+
+	struct seq_desc *seq_descs;
+	unsigned int seq_size;
+	unsigned int seq_tail;
 };
 
 int amdtp_domain_init(struct amdtp_domain *d);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/10] ALSA: firewire-lib: pool ideal sequence of syt offset and data block
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (7 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 08/10] ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  4:36 ` [PATCH 10/10] ALSA: firewire-lib: use sequence of syt offset and data block on pool in AMDTP domain Takashi Sakamoto
  2020-05-08  7:48 ` [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Iwai
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

In current implementation, sequence of syt offset and the number of data
blocks is generated when packets for outgoing stream are going to be
queued.

This commit generates and pools the sequence independently of the
processing of outgoing packets for future extension.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 68 +++++++++++++++++++++++++++++++++++
 sound/firewire/amdtp-stream.h |  6 ++++
 2 files changed, 74 insertions(+)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index f1c8611cfc70..a2af598e9b9a 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -905,14 +905,63 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
 	}
 }
 
+static void pool_ideal_seq_descs(struct amdtp_domain *d, unsigned int packets)
+{
+	struct amdtp_stream *irq_target = d->irq_target;
+	unsigned int seq_tail = d->seq_tail;
+	unsigned int seq_size = d->seq_size;
+	unsigned int min_avail;
+	struct amdtp_stream *s;
+
+	min_avail = d->seq_size;
+	list_for_each_entry(s, &d->streams, list) {
+		unsigned int seq_index;
+		unsigned int avail;
+
+		if (s->direction == AMDTP_IN_STREAM)
+			continue;
+
+		seq_index = s->ctx_data.rx.seq_index;
+		avail = d->seq_tail;
+		if (seq_index > avail)
+			avail += d->seq_size;
+		avail -= seq_index;
+
+		if (avail < min_avail)
+			min_avail = avail;
+	}
+
+	while (min_avail < packets) {
+		struct seq_desc *desc = d->seq_descs + seq_tail;
+
+		desc->syt_offset = calculate_syt_offset(&d->last_syt_offset,
+					&d->syt_offset_state, irq_target->sfc);
+		desc->data_blocks = calculate_data_blocks(&d->data_block_state,
+				!!(irq_target->flags & CIP_BLOCKING),
+				desc->syt_offset == CIP_SYT_NO_INFO,
+				irq_target->syt_interval, irq_target->sfc);
+
+		++seq_tail;
+		seq_tail %= seq_size;
+
+		++min_avail;
+	}
+
+	d->seq_tail = seq_tail;
+}
+
 static void irq_target_callback(struct fw_iso_context *context, u32 tstamp,
 				size_t header_length, void *header,
 				void *private_data)
 {
 	struct amdtp_stream *irq_target = private_data;
 	struct amdtp_domain *d = irq_target->domain;
+	unsigned int packets = header_length / sizeof(__be32);
 	struct amdtp_stream *s;
 
+	// Record enough entries with extra 3 cycles at least.
+	pool_ideal_seq_descs(d, packets + 3);
+
 	out_stream_callback(context, tstamp, header_length, header, irq_target);
 	if (amdtp_streaming_error(irq_target))
 		goto error;
@@ -1344,6 +1393,18 @@ static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle)
  */
 int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 {
+	static const struct {
+		unsigned int data_block;
+		unsigned int syt_offset;
+	} *entry, initial_state[] = {
+		[CIP_SFC_32000]  = {  4, 3072 },
+		[CIP_SFC_48000]  = {  6, 1024 },
+		[CIP_SFC_96000]  = { 12, 1024 },
+		[CIP_SFC_192000] = { 24, 1024 },
+		[CIP_SFC_44100]  = {  0,   67 },
+		[CIP_SFC_88200]  = {  0,   67 },
+		[CIP_SFC_176400] = {  0,   67 },
+	};
 	unsigned int events_per_buffer = d->events_per_buffer;
 	unsigned int events_per_period = d->events_per_period;
 	unsigned int idle_irq_interval;
@@ -1378,6 +1439,11 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 	d->seq_size = queue_size;
 	d->seq_tail = 0;
 
+	entry = &initial_state[s->sfc];
+	d->data_block_state = entry->data_block;
+	d->syt_offset_state = entry->syt_offset;
+	d->last_syt_offset = TICKS_PER_CYCLE;
+
 	if (ir_delay_cycle > 0) {
 		struct fw_card *fw_card = fw_parent_device(s->unit)->card;
 
@@ -1414,6 +1480,7 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 		} else {
 			// IT context starts immediately.
 			cycle_match = -1;
+			s->ctx_data.rx.seq_index = 0;
 		}
 
 		if (s != d->irq_target) {
@@ -1427,6 +1494,7 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 	s = d->irq_target;
 	s->ctx_data.rx.events_per_period = events_per_period;
 	s->ctx_data.rx.event_count = 0;
+	s->ctx_data.rx.seq_index = 0;
 
 	idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period,
 					 amdtp_rate_table[d->irq_target->sfc]);
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index 84a01efa5a85..11cff4cafd90 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -138,6 +138,8 @@ struct amdtp_stream {
 		struct {
 			// To calculate CIP data blocks and tstamp.
 			unsigned int transfer_delay;
+			unsigned int seq_index;
+
 			unsigned int data_block_state;
 			unsigned int last_syt_offset;
 			unsigned int syt_offset_state;
@@ -292,6 +294,10 @@ struct amdtp_domain {
 	struct seq_desc *seq_descs;
 	unsigned int seq_size;
 	unsigned int seq_tail;
+
+	unsigned int data_block_state;
+	unsigned int syt_offset_state;
+	unsigned int last_syt_offset;
 };
 
 int amdtp_domain_init(struct amdtp_domain *d);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/10] ALSA: firewire-lib: use sequence of syt offset and data block on pool in AMDTP domain
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (8 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 09/10] ALSA: firewire-lib: pool ideal sequence of syt offset and data block Takashi Sakamoto
@ 2020-05-08  4:36 ` Takashi Sakamoto
  2020-05-08  7:48 ` [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Iwai
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Sakamoto @ 2020-05-08  4:36 UTC (permalink / raw)
  To: clemens, tiwai; +Cc: alsa-devel

In previous commit, the sequence of syt offset and the number of data
blocks per packet is calculated for pool in AMDTP domain structure in
advance of processing outgoing packets.

This commit uses the sequence for outgoing packet processing to obsolete
per-stream processing of the sequence.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/amdtp-stream.c | 56 +++++++++++++----------------------
 sound/firewire/amdtp-stream.h |  4 ---
 2 files changed, 20 insertions(+), 40 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index a2af598e9b9a..f8586f75441d 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -747,34 +747,30 @@ static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle,
 	return syt & CIP_SYT_MASK;
 }
 
-static void generate_ideal_pkt_descs(struct amdtp_stream *s,
-				     struct pkt_desc *descs,
-				     const __be32 *ctx_header,
-				     unsigned int packets)
+static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs,
+			       const __be32 *ctx_header, unsigned int packets,
+			       const struct seq_desc *seq_descs,
+			       unsigned int seq_size)
 {
 	unsigned int dbc = s->data_block_counter;
+	unsigned int seq_index = s->ctx_data.rx.seq_index;
 	int i;
 
 	for (i = 0; i < packets; ++i) {
 		struct pkt_desc *desc = descs + i;
 		unsigned int index = (s->packet_index + i) % s->queue_size;
-		unsigned int syt_offset;
+		const struct seq_desc *seq = seq_descs + seq_index;
+		unsigned int syt;
 
 		desc->cycle = compute_it_cycle(*ctx_header, s->queue_size);
-		syt_offset = calculate_syt_offset(
-				&s->ctx_data.rx.last_syt_offset,
-				&s->ctx_data.rx.syt_offset_state, s->sfc);
-		if (syt_offset != CIP_SYT_NO_INFO) {
-			desc->syt = compute_syt(syt_offset, desc->cycle,
-						s->ctx_data.rx.transfer_delay);
-		} else {
-			desc->syt = syt_offset;
+
+		syt = seq->syt_offset;
+		if (syt != CIP_SYT_NO_INFO) {
+			syt = compute_syt(syt, desc->cycle,
+					  s->ctx_data.rx.transfer_delay);
 		}
-		desc->data_blocks =
-			calculate_data_blocks(&s->ctx_data.rx.data_block_state,
-					      !!(s->flags & CIP_BLOCKING),
-					      desc->syt == CIP_SYT_NO_INFO,
-					      s->syt_interval, s->sfc);
+		desc->syt = syt;
+		desc->data_blocks = seq->data_blocks;
 
 		if (s->flags & CIP_DBC_IS_END_EVENT)
 			dbc = (dbc + desc->data_blocks) & 0xff;
@@ -786,10 +782,13 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s,
 
 		desc->ctx_payload = s->buffer.packets[index].buffer;
 
+		seq_index = (seq_index + 1) % seq_size;
+
 		++ctx_header;
 	}
 
 	s->data_block_counter = dbc;
+	s->ctx_data.rx.seq_index = seq_index;
 }
 
 static inline void cancel_stream(struct amdtp_stream *s)
@@ -818,6 +817,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 				void *private_data)
 {
 	struct amdtp_stream *s = private_data;
+	const struct amdtp_domain *d = s->domain;
 	const __be32 *ctx_header = header;
 	unsigned int events_per_period = s->ctx_data.rx.events_per_period;
 	unsigned int event_count = s->ctx_data.rx.event_count;
@@ -830,7 +830,8 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
 	// Calculate the number of packets in buffer and check XRUN.
 	packets = header_length / sizeof(*ctx_header);
 
-	generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets);
+	generate_pkt_descs(s, s->pkt_descs, ctx_header, packets, d->seq_descs,
+			   d->seq_size);
 
 	process_ctx_payloads(s, s->pkt_descs, packets);
 
@@ -1037,18 +1038,6 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 			      int start_cycle, unsigned int queue_size,
 			      unsigned int idle_irq_interval)
 {
-	static const struct {
-		unsigned int data_block;
-		unsigned int syt_offset;
-	} *entry, initial_state[] = {
-		[CIP_SFC_32000]  = {  4, 3072 },
-		[CIP_SFC_48000]  = {  6, 1024 },
-		[CIP_SFC_96000]  = { 12, 1024 },
-		[CIP_SFC_192000] = { 24, 1024 },
-		[CIP_SFC_44100]  = {  0,   67 },
-		[CIP_SFC_88200]  = {  0,   67 },
-		[CIP_SFC_176400] = {  0,   67 },
-	};
 	bool is_irq_target = (s == s->domain->irq_target);
 	unsigned int ctx_header_size;
 	unsigned int max_ctx_payload_size;
@@ -1072,12 +1061,7 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
 
 		s->data_block_counter = UINT_MAX;
 	} else {
-		entry = &initial_state[s->sfc];
-
 		s->data_block_counter = 0;
-		s->ctx_data.rx.data_block_state = entry->data_block;
-		s->ctx_data.rx.syt_offset_state = entry->syt_offset;
-		s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE;
 	}
 
 	/* initialize packet buffer */
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index 11cff4cafd90..703b710aaf7f 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -140,10 +140,6 @@ struct amdtp_stream {
 			unsigned int transfer_delay;
 			unsigned int seq_index;
 
-			unsigned int data_block_state;
-			unsigned int last_syt_offset;
-			unsigned int syt_offset_state;
-
 			// To generate CIP header.
 			unsigned int fdf;
 			int syt_override;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure
  2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
                   ` (9 preceding siblings ...)
  2020-05-08  4:36 ` [PATCH 10/10] ALSA: firewire-lib: use sequence of syt offset and data block on pool in AMDTP domain Takashi Sakamoto
@ 2020-05-08  7:48 ` Takashi Iwai
  10 siblings, 0 replies; 12+ messages in thread
From: Takashi Iwai @ 2020-05-08  7:48 UTC (permalink / raw)
  To: Takashi Sakamoto; +Cc: alsa-devel, clemens

On Fri, 08 May 2020 06:36:25 +0200,
Takashi Sakamoto wrote:
> 
> Hi,
> 
> In current implementation, the packets for outgoing AMDTP streams are
> processed by per-stream calculation of syt offset and the number of data
> blocks per packet.
> 
> This patchset is a preparation for future extension that the packets for
> outgoing AMDTP streams are processed according to the result of 'sampling
> clock recovery' in IEC 61883-6:2005 from selected incoming AMDTP stream.
> The preparation is to process packets for outgoing AMDTP streams by pool
> in AMDTP domain structure for the sequence of syt offset and the number
> of data blocks. The way to generate sequence is still the same as the
> current implementation, which generates by ideal sampling transmission
> frequency against IEEE 1394 bus clock.
> 
> Takashi Sakamoto (10):
>   ALSA: firewire-lib: fix invalid assignment to union data for
>     directional parameter
>   ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI
>     isoc descriptor
>   ALSA: firewire-lib: add reference to domain structure from stream
>     structure
>   ALSA: firewire-lib: code refactoring for parameters of packet queue
>     and IRQ timing
>   ALSA: firewire-lib: code refactoring for syt computation
>   ALSA: firewire-lib: code refactoring for syt offset calculation
>   ALSA: firewire-lib: code refactoring for data block calculation
>   ALSA: firewire-lib: add cache for packet sequence to AMDTP domain
>     structure
>   ALSA: firewire-lib: pool ideal sequence of syt offset and data block
>   ALSA: firewire-lib: use sequence of syt offset and data block on pool
>     in AMDTP domain

Applied all ten patches to for-next branch now.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-05-08  7:49 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-08  4:36 [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 01/10] ALSA: firewire-lib: fix invalid assignment to union data for directional parameter Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 02/10] ALSA: firewire-lib: use macro for maximum value of second in 1394 OHCI isoc descriptor Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 03/10] ALSA: firewire-lib: add reference to domain structure from stream structure Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 04/10] ALSA: firewire-lib: code refactoring for parameters of packet queue and IRQ timing Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 05/10] ALSA: firewire-lib: code refactoring for syt computation Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 06/10] ALSA: firewire-lib: code refactoring for syt offset calculation Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 07/10] ALSA: firewire-lib: code refactoring for data block calculation Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 08/10] ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 09/10] ALSA: firewire-lib: pool ideal sequence of syt offset and data block Takashi Sakamoto
2020-05-08  4:36 ` [PATCH 10/10] ALSA: firewire-lib: use sequence of syt offset and data block on pool in AMDTP domain Takashi Sakamoto
2020-05-08  7:48 ` [PATCH 00/10] ALSA: firewire-lib: pool sequence of syt offset and data blocks in AMDTP domain structure Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).