Skip to content

Commit

Permalink
ALSA: oxfw: start duplex streams if supported
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
takaswie authored and tiwai committed Jun 12, 2019
1 parent 521b2e1 commit 20358d4
Showing 1 changed file with 49 additions and 53 deletions.
102 changes: 49 additions & 53 deletions sound/firewire/oxfw/oxfw-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

/*
Expand Down

0 comments on commit 20358d4

Please sign in to comment.