ALSA: firewire-digi00x: support AMDTP domain
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 4 Aug 2019 06:21:34 +0000 (15:21 +0900)
committerTakashi Iwai <tiwai@suse.de>
Mon, 5 Aug 2019 17:57:26 +0000 (19:57 +0200)
This commit adds AMDTP domain support for ALSA firewire-digi00x driver.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/digi00x/digi00x-stream.c
sound/firewire/digi00x/digi00x.h

index cff193f00a976541c354dcd8709eda5c98ead206..d6a92460060f649eb7f006e4215a4dd36fdee855 100644 (file)
@@ -126,9 +126,6 @@ static void finish_session(struct snd_dg00x *dg00x)
 {
        __be32 data;
 
-       amdtp_stream_stop(&dg00x->tx_stream);
-       amdtp_stream_stop(&dg00x->rx_stream);
-
        data = cpu_to_be32(0x00000003);
        snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
                           DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET,
@@ -265,13 +262,23 @@ int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
        if (err < 0)
                destroy_stream(dg00x, &dg00x->rx_stream);
 
+       err = amdtp_domain_init(&dg00x->domain);
+       if (err < 0) {
+               destroy_stream(dg00x, &dg00x->rx_stream);
+               destroy_stream(dg00x, &dg00x->tx_stream);
+       }
+
        return err;
 }
 
-// This function should be called before starting streams or after stopping
-// streams.
+/*
+ * This function should be called before starting streams or after stopping
+ * streams.
+ */
 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
 {
+       amdtp_domain_destroy(&dg00x->domain);
+
        destroy_stream(dg00x, &dg00x->rx_stream);
        destroy_stream(dg00x, &dg00x->tx_stream);
 }
@@ -288,6 +295,8 @@ int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate)
                rate = curr_rate;
 
        if (dg00x->substreams_counter == 0 || curr_rate != rate) {
+               amdtp_domain_stop(&dg00x->domain);
+
                finish_session(dg00x);
 
                fw_iso_resources_free(&dg00x->tx_resources);
@@ -320,8 +329,10 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
                return 0;
 
        if (amdtp_streaming_error(&dg00x->tx_stream) ||
-           amdtp_streaming_error(&dg00x->rx_stream))
+           amdtp_streaming_error(&dg00x->rx_stream)) {
+               amdtp_domain_stop(&dg00x->domain);
                finish_session(dg00x);
+       }
 
        if (generation != fw_parent_device(dg00x->unit)->card->generation) {
                err = fw_iso_resources_update(&dg00x->tx_resources);
@@ -338,36 +349,30 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
         * which source of clock is used.
         */
        if (!amdtp_stream_running(&dg00x->rx_stream)) {
+               int spd = fw_parent_device(dg00x->unit)->max_speed;
+
                err = begin_session(dg00x);
                if (err < 0)
                        goto error;
 
-               err = amdtp_stream_start(&dg00x->rx_stream,
-                               dg00x->rx_resources.channel,
-                               fw_parent_device(dg00x->unit)->max_speed);
+               err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
+                                             dg00x->rx_resources.channel, spd);
                if (err < 0)
                        goto error;
 
-               if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
-                                             CALLBACK_TIMEOUT)) {
-                       err = -ETIMEDOUT;
+               err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
+                                             dg00x->tx_resources.channel, spd);
+               if (err < 0)
                        goto error;
-               }
-       }
 
-       /*
-        * The value of SYT field in transmitted packets is always 0x0000. Thus,
-        * duplex streams with timestamp synchronization cannot be built.
-        */
-       if (!amdtp_stream_running(&dg00x->tx_stream)) {
-               err = amdtp_stream_start(&dg00x->tx_stream,
-                               dg00x->tx_resources.channel,
-                               fw_parent_device(dg00x->unit)->max_speed);
+               err = amdtp_domain_start(&dg00x->domain);
                if (err < 0)
                        goto error;
 
-               if (!amdtp_stream_wait_callback(&dg00x->tx_stream,
-                                             CALLBACK_TIMEOUT)) {
+               if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
+                                               CALLBACK_TIMEOUT) ||
+                   !amdtp_stream_wait_callback(&dg00x->tx_stream,
+                                               CALLBACK_TIMEOUT)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
@@ -375,6 +380,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
 
        return 0;
 error:
+       amdtp_domain_stop(&dg00x->domain);
        finish_session(dg00x);
 
        return err;
@@ -383,6 +389,7 @@ error:
 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
 {
        if (dg00x->substreams_counter == 0) {
+               amdtp_domain_stop(&dg00x->domain);
                finish_session(dg00x);
 
                fw_iso_resources_free(&dg00x->tx_resources);
index 0994d191ccda49cf9ccd15a4e4f03a5ac7f4ec02..8041c65f27362ef0db2d2c4122e1981a479444d1 100644 (file)
@@ -59,6 +59,8 @@ struct snd_dg00x {
 
        /* Console models have additional MIDI ports for control surface. */
        bool is_console;
+
+       struct amdtp_domain domain;
 };
 
 #define DG00X_ADDR_BASE                0xffffe0000000ull