aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2019-06-12 17:44:16 +0900
committerTakashi Iwai <tiwai@suse.de>2019-06-12 15:26:55 +0200
commit20358d4460bd4aa833b1ad79b79763887d9b75e4 (patch)
tree726e28aa76278e5a7738e4a4ee6899c22222465d /sound/firewire
parentALSA: oxfw: set packet parameter according to current configuration (diff)
downloadlinux-dev-20358d4460bd4aa833b1ad79b79763887d9b75e4.tar.xz
linux-dev-20358d4460bd4aa833b1ad79b79763887d9b75e4.zip
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.c102
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);
+ }
}
/*