ALSA: oxfw: start duplex streams if supported
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Wed, 12 Jun 2019 08:44:16 +0000 (17:44 +0900)
committerTakashi Iwai <tiwai@suse.de>
Wed, 12 Jun 2019 13:26:55 +0000 (15:26 +0200)
It's inconvenient to handle two isochronous context separately
each other. This commit unifies the counters to handle the two
at the same time.

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

index 1691fdc1a5753015af20b7591a6b4c638dd66466..bb4ba6c196ea7ef2fe1381b9f9ea4705ba483edd 100644 (file)
@@ -254,96 +254,92 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw,
                                  struct amdtp_stream *stream,
                                  unsigned int rate, unsigned int pcm_channels)
 {
-       struct amdtp_stream *opposite;
        struct snd_oxfw_stream_formation formation;
        enum avc_general_plug_dir dir;
-       unsigned int substreams, opposite_substreams;
        int err = 0;
 
-       if (stream == &oxfw->tx_stream) {
-               substreams = oxfw->capture_substreams;
-               opposite = &oxfw->rx_stream;
-               opposite_substreams = oxfw->playback_substreams;
-               dir = AVC_GENERAL_PLUG_DIR_OUT;
-       } else {
-               substreams = oxfw->playback_substreams;
-               opposite_substreams = oxfw->capture_substreams;
+       if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0)
+               return -EIO;
 
-               if (oxfw->has_output)
-                       opposite = &oxfw->rx_stream;
-               else
-                       opposite = NULL;
-
-               dir = AVC_GENERAL_PLUG_DIR_IN;
+       // Considering JACK/FFADO streaming:
+       // TODO: This can be removed hwdep functionality becomes popular.
+       err = check_connection_used_by_others(oxfw, &oxfw->rx_stream);
+       if (err < 0)
+               return err;
+       if (oxfw->has_output) {
+               err = check_connection_used_by_others(oxfw, &oxfw->tx_stream);
+               if (err < 0)
+                       return err;
        }
 
-       if (substreams == 0)
-               goto end;
-
-       /*
-        * Considering JACK/FFADO streaming:
-        * TODO: This can be removed hwdep functionality becomes popular.
-        */
-       err = check_connection_used_by_others(oxfw, stream);
-       if (err < 0)
-               goto end;
+       if (stream == &oxfw->tx_stream)
+               dir = AVC_GENERAL_PLUG_DIR_OUT;
+       else
+               dir = AVC_GENERAL_PLUG_DIR_IN;
 
        err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
        if (err < 0)
-               goto end;
+               return err;
        if (rate == 0)
                rate = formation.rate;
        if (pcm_channels == 0)
                pcm_channels = formation.pcm;
 
        if (formation.rate != rate || formation.pcm != pcm_channels ||
-           amdtp_streaming_error(stream)) {
-               if (opposite != NULL) {
-                       err = check_connection_used_by_others(oxfw, opposite);
-                       if (err < 0)
-                               goto end;
-                       stop_stream(oxfw, opposite);
-               }
-               stop_stream(oxfw, stream);
+           amdtp_streaming_error(&oxfw->rx_stream) ||
+           amdtp_streaming_error(&oxfw->tx_stream)) {
+               stop_stream(oxfw, &oxfw->rx_stream);
+               if (oxfw->has_output)
+                       stop_stream(oxfw, &oxfw->tx_stream);
 
                err = set_stream_format(oxfw, stream, rate, pcm_channels);
                if (err < 0) {
                        dev_err(&oxfw->unit->device,
                                "fail to set stream format: %d\n", err);
-                       goto end;
+                       return err;
+               }
+       }
+
+       if (!amdtp_stream_running(&oxfw->rx_stream)) {
+               err = start_stream(oxfw, &oxfw->rx_stream);
+               if (err < 0) {
+                       dev_err(&oxfw->unit->device,
+                               "fail to start rx stream: %d\n", err);
+                       goto error;
                }
+       }
 
-               /* Start opposite stream if needed. */
-               if (opposite && !amdtp_stream_running(opposite) &&
-                   (opposite_substreams > 0)) {
-                       err = start_stream(oxfw, opposite);
+       if (oxfw->has_output) {
+               if (!amdtp_stream_running(&oxfw->tx_stream)) {
+                       err = start_stream(oxfw, &oxfw->tx_stream);
                        if (err < 0) {
                                dev_err(&oxfw->unit->device,
-                                       "fail to restart stream: %d\n", err);
-                               goto end;
+                                       "fail to start tx stream: %d\n", err);
+                               goto error;
                        }
                }
        }
 
-       /* Start requested stream. */
-       if (!amdtp_stream_running(stream)) {
-               err = start_stream(oxfw, stream);
-               if (err < 0)
-                       dev_err(&oxfw->unit->device,
-                               "fail to start stream: %d\n", err);
+       return 0;
+error:
+       stop_stream(oxfw, &oxfw->rx_stream);
+       cmp_connection_break(&oxfw->in_conn);
+       if (oxfw->has_output) {
+               stop_stream(oxfw, &oxfw->tx_stream);
+               cmp_connection_break(&oxfw->out_conn);
        }
-end:
        return err;
 }
 
 void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw,
                                  struct amdtp_stream *stream)
 {
-       if (((stream == &oxfw->tx_stream) && (oxfw->capture_substreams > 0)) ||
-           ((stream == &oxfw->rx_stream) && (oxfw->playback_substreams > 0)))
-               return;
+       if (oxfw->capture_substreams == 0 && oxfw->playback_substreams == 0) {
+               stop_stream(oxfw, &oxfw->rx_stream);
 
-       stop_stream(oxfw, stream);
+               if (oxfw->has_output)
+                       stop_stream(oxfw, &oxfw->tx_stream);
+       }
 }
 
 /*