ALSA: firewire-lib: move parameter for pcm frame multiplier from context payload...
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Tue, 10 Jan 2023 13:49:31 +0000 (22:49 +0900)
committerTakashi Iwai <tiwai@suse.de>
Thu, 12 Jan 2023 11:14:49 +0000 (12:14 +0100)
The current implementation delegates the task to calculate the number of
processed PCM frames into the context payload processing layer. It looks
good as long as frame calculation is done for a single purpose.
Nevertheless, another purpose, the computation of extra delay for the
runtime of PCM substream, requires frame calculation, too.

This commit refactors the current implementation so that the packet stream
processing layer is responsible for the calculation of PCM frame, too. The
member is moved to stream structure for multiplier between data block
count and PCM frame count.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20230110134933.322794-2-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/amdtp-am824.c
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.h
sound/firewire/digi00x/amdtp-dot.c
sound/firewire/fireface/amdtp-ff.c
sound/firewire/motu/amdtp-motu.c
sound/firewire/tascam/amdtp-tascam.c

index cf55f7784d23355db225ffc857bb123771ce3295..b849f529fcba6eefac0aad3cab3c6e5bd369b099 100644 (file)
@@ -36,8 +36,6 @@ struct amdtp_am824 {
 
        u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM];
        u8 midi_position;
-
-       unsigned int frame_multiplier;
 };
 
 /**
@@ -59,8 +57,8 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
 {
        struct amdtp_am824 *p = s->protocol;
        unsigned int midi_channels;
-       unsigned int i;
-       int err;
+       unsigned int pcm_frame_multiplier;
+       int i, err;
 
        if (amdtp_stream_running(s))
                return -EINVAL;
@@ -77,8 +75,18 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
            WARN_ON(midi_channels > AM824_MAX_CHANNELS_FOR_MIDI))
                return -EINVAL;
 
-       err = amdtp_stream_set_parameters(s, rate,
-                                         pcm_channels + midi_channels);
+       /*
+        * In IEC 61883-6, one data block represents one event. In ALSA, one
+        * event equals to one PCM frame. But Dice has a quirk at higher
+        * sampling rate to transfer two PCM frames in one data block.
+        */
+       if (double_pcm_frames)
+               pcm_frame_multiplier = 2;
+       else
+               pcm_frame_multiplier = 1;
+
+       err = amdtp_stream_set_parameters(s, rate, pcm_channels + midi_channels,
+                                         pcm_frame_multiplier);
        if (err < 0)
                return err;
 
@@ -88,16 +96,6 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
        p->pcm_channels = pcm_channels;
        p->midi_ports = midi_ports;
 
-       /*
-        * In IEC 61883-6, one data block represents one event. In ALSA, one
-        * event equals to one PCM frame. But Dice has a quirk at higher
-        * sampling rate to transfer two PCM frames in one data block.
-        */
-       if (double_pcm_frames)
-               p->frame_multiplier = 2;
-       else
-               p->frame_multiplier = 1;
-
        /* init the position map for PCM and MIDI channels */
        for (i = 0; i < pcm_channels; i++)
                p->pcm_positions[i] = i;
@@ -361,7 +359,7 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s,
 
                if (pcm) {
                        write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
-                       pcm_frames += data_blocks * p->frame_multiplier;
+                       pcm_frames += data_blocks * s->pcm_frame_multiplier;
                } else {
                        write_pcm_silence(s, buf, data_blocks);
                }
@@ -392,7 +390,7 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
 
                if (pcm) {
                        read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
-                       pcm_frames += data_blocks * p->frame_multiplier;
+                       pcm_frames += data_blocks * s->pcm_frame_multiplier;
                }
 
                if (p->midi_ports) {
index 65720ae866cbb41707f4635c85e8a5d654506552..453751e4fef840a20222c7ead7745e9462997f66 100644 (file)
@@ -271,12 +271,14 @@ EXPORT_SYMBOL(amdtp_stream_add_pcm_hw_constraints);
  * @s: the AMDTP stream to configure
  * @rate: the sample rate
  * @data_block_quadlets: the size of a data block in quadlet unit
+ * @pcm_frame_multiplier: the multiplier to compute the number of PCM frames by the number of AMDTP
+ *                       events.
  *
  * The parameters must be set before the stream is started, and must not be
  * changed while the stream is running.
  */
 int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
-                               unsigned int data_block_quadlets)
+                               unsigned int data_block_quadlets, unsigned int pcm_frame_multiplier)
 {
        unsigned int sfc;
 
@@ -298,6 +300,8 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
        if (s->flags & CIP_BLOCKING)
                s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
 
+       s->pcm_frame_multiplier = pcm_frame_multiplier;
+
        return 0;
 }
 EXPORT_SYMBOL(amdtp_stream_set_parameters);
@@ -1032,16 +1036,25 @@ static inline void cancel_stream(struct amdtp_stream *s)
 }
 
 static void process_ctx_payloads(struct amdtp_stream *s,
-                                const struct pkt_desc *descs,
+                                const struct pkt_desc *desc,
                                 unsigned int count)
 {
        struct snd_pcm_substream *pcm;
-       unsigned int pcm_frames;
+       int i;
 
        pcm = READ_ONCE(s->pcm);
-       pcm_frames = s->process_ctx_payloads(s, descs, count, pcm);
-       if (pcm)
-               update_pcm_pointers(s, pcm, pcm_frames);
+       (void)s->process_ctx_payloads(s, desc, count, pcm);
+
+       if (pcm) {
+               unsigned int data_block_count = 0;
+
+               for (i = 0; i < count; ++i) {
+                       data_block_count += desc->data_blocks;
+                       desc = amdtp_stream_next_packet_desc(s, desc);
+               }
+
+               update_pcm_pointers(s, pcm, data_block_count * s->pcm_frame_multiplier);
+       }
 }
 
 static void process_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length,
index a8dd1c3ec8d91b9b46c2403f66f569506f57cc0f..35b48f9ddbf78c1209bea47e24ff6035a13f8696 100644 (file)
@@ -190,6 +190,7 @@ struct amdtp_stream {
        struct snd_pcm_substream *pcm;
        snd_pcm_uframes_t pcm_buffer_pointer;
        unsigned int pcm_period_pointer;
+       unsigned int pcm_frame_multiplier;
 
        // To start processing content of packets at the same cycle in several contexts for
        // each direction.
@@ -216,7 +217,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
 void amdtp_stream_destroy(struct amdtp_stream *s);
 
 int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
-                               unsigned int data_block_quadlets);
+                               unsigned int data_block_quadlets, unsigned int pcm_frame_multiplier);
 unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s);
 
 void amdtp_stream_update(struct amdtp_stream *s);
index fcae7d07aa0393ef784c11e70c31a222e50ed90c..b3f67af2d3b1c09dad2ef10f722dc02ad3223ef9 100644 (file)
@@ -123,7 +123,7 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
         * A first data channel is for MIDI messages, the rest is Multi Bit
         * Linear Audio data channel.
         */
-       err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1);
+       err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1, 1);
        if (err < 0)
                return err;
 
index 2402e2be87a674e26fe15b716ed63c54fcbed95e..27943b7f86fa730d1700e14958b97dbe01574193 100644 (file)
@@ -24,7 +24,7 @@ int amdtp_ff_set_parameters(struct amdtp_stream *s, unsigned int rate,
        p->pcm_channels = pcm_channels;
        data_channels = pcm_channels;
 
-       return amdtp_stream_set_parameters(s, rate, data_channels);
+       return amdtp_stream_set_parameters(s, rate, data_channels, 1);
 }
 
 static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
index ea0063cec5fbfe820aaa379cdaa335afbb80560d..4153527b5e081f8962ae95535cd191f9c73deda2 100644 (file)
@@ -73,7 +73,7 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
        data_chunks = formats->msg_chunks + pcm_chunks;
        data_block_quadlets = 1 + DIV_ROUND_UP(data_chunks * 3, 4);
 
-       err = amdtp_stream_set_parameters(s, rate, data_block_quadlets);
+       err = amdtp_stream_set_parameters(s, rate, data_block_quadlets, 1);
        if (err < 0)
                return err;
 
index c367a6ee61217f3226ce29a0090d83ddbc5525a3..bb4cf2d26d1b8a0ac8aa992df294bbf3f16ce56e 100644 (file)
@@ -29,7 +29,7 @@ int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate)
        if (s->direction == AMDTP_IN_STREAM)
                data_channels += 2;
 
-       return amdtp_stream_set_parameters(s, rate, data_channels);
+       return amdtp_stream_set_parameters(s, rate, data_channels, 1);
 }
 
 static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,