Commit 2f21a177 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

ALSA: firewire-lib: transfer rx packets on-the-fly when replaying



Models in below series start transmission of packet after receiving the
sequence of packets:

 * Digidesign Digi00x family
 * RME Fireface series

Additionally, models in Tascam FireWire series start multiplexing PCM
frames into packets enough after receiving packets. It's required to
transfer packets on-the-fly for the above models according to nominal
sampling transfer frequency before starting sequence replay.

This commit allows drivers to decide whether the engine transfers packet
on-the-fly or not.

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20210527122611.173711-4-o-takashi@sakamocchi.jp


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 39c2649c
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -577,10 +577,23 @@ static void pool_seq_descs(struct amdtp_stream *s, unsigned int count)
{
	struct amdtp_domain *d = s->domain;

	if (!d->replay.enable || !s->ctx_data.rx.replay_target)
	if (!d->replay.enable || !s->ctx_data.rx.replay_target) {
		pool_ideal_seq_descs(s, count);
	else
	} else {
		if (!d->replay.on_the_fly) {
			pool_replayed_seq(s, count);
		} else {
			struct amdtp_stream *tx = s->ctx_data.rx.replay_target;
			const unsigned int cache_size = tx->ctx_data.tx.cache.size;
			const unsigned int cache_head = s->ctx_data.rx.cache_head;
			unsigned int cached_cycles = calculate_cached_cycle_count(tx, cache_head);

			if (cached_cycles > count && cached_cycles > cache_size / 2)
				pool_replayed_seq(s, count);
			else
				pool_ideal_seq_descs(s, count);
		}
	}
}

static void update_pcm_pointers(struct amdtp_stream *s,
@@ -1444,7 +1457,7 @@ static void irq_target_callback_skip(struct fw_iso_context *context, u32 tstamp,
	skip_rx_packets(context, tstamp, header_length, header, private_data);
	process_ctxs_in_domain(d);

	if (d->replay.enable) {
	if (d->replay.enable && !d->replay.on_the_fly) {
		unsigned int rx_count = 0;
		unsigned int rx_ready_count = 0;
		struct amdtp_stream *rx;
@@ -1929,8 +1942,11 @@ static int make_association(struct amdtp_domain *d)
 *			 contexts.
 * @replay_seq: whether to replay the sequence of packet in IR context for the sequence of packet in
 *		IT context.
 * @replay_on_the_fly: transfer rx packets according to nominal frequency, then begin to replay
 *		       according to arrival of events in tx packets.
 */
int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq)
int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq,
		       bool replay_on_the_fly)
{
	unsigned int events_per_buffer = d->events_per_buffer;
	unsigned int events_per_period = d->events_per_period;
@@ -1944,6 +1960,7 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles,
			return err;
	}
	d->replay.enable = replay_seq;
	d->replay.on_the_fly = replay_on_the_fly;

	// Select an IT context as IRQ target.
	list_for_each_entry(s, &d->streams, list) {
+4 −2
Original line number Diff line number Diff line
@@ -303,7 +303,8 @@ struct amdtp_domain {
	} processing_cycle;

	struct {
		bool enable;
		bool enable:1;
		bool on_the_fly:1;
	} replay;
};

@@ -313,7 +314,8 @@ void amdtp_domain_destroy(struct amdtp_domain *d);
int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s,
			    int channel, int speed);

int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq);
int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq,
		       bool replay_on_the_fly);
void amdtp_domain_stop(struct amdtp_domain *d);

static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d,
+1 −1
Original line number Diff line number Diff line
@@ -652,7 +652,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
		// MEMO: In the early stage of packet streaming, the device transfers NODATA packets.
		// After several hundred cycles, it begins to multiplex event into the packet with
		// syt information.
		err = amdtp_domain_start(&bebob->domain, tx_init_skip_cycles, false);
		err = amdtp_domain_start(&bebob->domain, tx_init_skip_cycles, false, false);
		if (err < 0)
			goto error;

+1 −1
Original line number Diff line number Diff line
@@ -459,7 +459,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice)
			goto error;
		}

		err = amdtp_domain_start(&dice->domain, 0, false);
		err = amdtp_domain_start(&dice->domain, 0, false, false);
		if (err < 0)
			goto error;

+1 −1
Original line number Diff line number Diff line
@@ -375,7 +375,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
		if (err < 0)
			goto error;

		err = amdtp_domain_start(&dg00x->domain, 0, false);
		err = amdtp_domain_start(&dg00x->domain, 0, false, false);
		if (err < 0)
			goto error;

Loading