diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2019-06-12 17:44:16 +0900 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-06-12 15:26:55 +0200 |
commit | 20358d4460bd4aa833b1ad79b79763887d9b75e4 (patch) | |
tree | 726e28aa76278e5a7738e4a4ee6899c22222465d /sound/firewire | |
parent | 521b2e11fad0b4d6b36727ecca624710b5f81fd1 (diff) | |
download | linux-20358d4460bd4aa833b1ad79b79763887d9b75e4.tar.bz2 |
ALSA: oxfw: start duplex streams if supported
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>
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/oxfw/oxfw-stream.c | 102 |
1 files changed, 49 insertions, 53 deletions
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 1691fdc1a575..bb4ba6c196ea 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -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); + } } /* |