ALSA: fireface: perform sequence replay for media clock recovery
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 31 May 2021 02:51:03 +0000 (11:51 +0900)
committerTakashi Iwai <tiwai@suse.de>
Tue, 1 Jun 2021 06:19:51 +0000 (08:19 +0200)
This commit takes ALSA fireface driver to perform sequence replay for
media clock recovery.

The protocol specific to RME Fireface series is not compliant to
IEC 61883-1/6 since it has no CIP header, therefore presentation time
is not used for media clock recovery. The sequence of the number of data
blocks per packet is important.

I note that the device skips an isochronous cycle corresponding to an
empty packet or a NODATA packet in blocking transmission method of
IEC 61883-1/6. For sequence replay, the cycle is handled as receiving an
empty packet. Furthermore, it doesn't start packet transmission till
receiving any packet.

The sequence replay is tested with below models:

* Fireface 400
* Fireface 800
* Fireface 802

I note that it is better to initialize Fireface 400 in advance by
initialization transaction implemented in snd-fireface-ctl-service of
snd-firewire-ctl-services project. You can see whether initialized or
not by HOST LED on the device. Unless, the device often stops packet
transmission even if session starts.

I guess the sequence replay also works well with below models:

* Fireface UFX
* Fireface UCX

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20210531025103.17880-7-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/fireface/amdtp-ff.c
sound/firewire/fireface/ff-stream.c

index 119c007..98177b0 100644 (file)
@@ -168,6 +168,6 @@ int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit,
        else
                process_ctx_payloads = process_it_ctx_payloads;
 
-       return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0,
+       return amdtp_stream_init(s, unit, dir, CIP_BLOCKING | CIP_UNAWARE_SYT | CIP_NO_HEADER, 0,
                                 process_ctx_payloads, sizeof(struct amdtp_ff));
 }
index 97c356f..95bf405 100644 (file)
@@ -199,7 +199,11 @@ 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, false);
+               // NOTE: The device doesn't transfer packets unless receiving any packet. The
+               // sequence of tx packets includes cycle skip corresponding to empty packet or
+               // NODATA packet in IEC 61883-1/6. The sequence of the number of data blocks per
+               // packet is important for media clock recovery.
+               err = amdtp_domain_start(&ff->domain, 0, true, true);
                if (err < 0)
                        goto error;