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>
This commit is contained in:
Родитель
39c2649c71
Коммит
2f21a17763
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = amdtp_domain_start(&ff->domain, 0, false);
|
||||
err = amdtp_domain_start(&ff->domain, 0, false, false);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = amdtp_domain_start(&efw->domain, 0, false);
|
||||
err = amdtp_domain_start(&efw->domain, 0, false, false);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
|||
if (err < 0)
|
||||
goto stop_streams;
|
||||
|
||||
err = amdtp_domain_start(&motu->domain, 0, false);
|
||||
err = amdtp_domain_start(&motu->domain, 0, false, false);
|
||||
if (err < 0)
|
||||
goto stop_streams;
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
|
|||
}
|
||||
}
|
||||
|
||||
err = amdtp_domain_start(&oxfw->domain, 0, false);
|
||||
err = amdtp_domain_start(&oxfw->domain, 0, false, false);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -473,7 +473,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = amdtp_domain_start(&tscm->domain, 0, false);
|
||||
err = amdtp_domain_start(&tscm->domain, 0, false, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче