diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2021-05-27 21:26:11 +0900 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-05-28 11:06:33 +0200 |
commit | 2f21a177631ae969537cf4ed602293d9aac9f73e (patch) | |
tree | 68c494830ef12aea088b1d57ef82c11e62b31434 /sound/firewire/amdtp-stream.c | |
parent | 39c2649c71d87cda8af6547076ab7abec4b15b23 (diff) |
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: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20210527122611.173711-4-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/amdtp-stream.c')
-rw-r--r-- | sound/firewire/amdtp-stream.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 47ea03370858..d0e9b417c019 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -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 - pool_replayed_seq(s, count); + } 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) { |