aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/dice/dice-stream.c119
1 files changed, 62 insertions, 57 deletions
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index b792e7bb6b14..e93ceff8ce39 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -284,6 +284,63 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
return err;
}
+static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)
+{
+ struct reg_params tx_params, rx_params;
+ int i;
+ int err;
+
+ err = get_register_params(dice, &tx_params, &rx_params);
+ if (err < 0)
+ return err;
+
+ /* Stop transmission. */
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
+ snd_dice_transaction_clear_enable(dice);
+ release_resources(dice);
+
+ err = ensure_phase_lock(dice);
+ if (err < 0) {
+ dev_err(&dice->unit->device, "fail to ensure phase lock\n");
+ return err;
+ }
+
+ /* Start both streams. */
+ err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
+ if (err < 0)
+ goto error;
+ err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
+ if (err < 0)
+ goto error;
+
+ err = snd_dice_transaction_set_enable(dice);
+ if (err < 0) {
+ dev_err(&dice->unit->device, "fail to enable interface\n");
+ goto error;
+ }
+
+ for (i = 0; i < MAX_STREAMS; i++) {
+ if ((i < tx_params.count &&
+ !amdtp_stream_wait_callback(&dice->tx_stream[i],
+ CALLBACK_TIMEOUT)) ||
+ (i < rx_params.count &&
+ !amdtp_stream_wait_callback(&dice->rx_stream[i],
+ CALLBACK_TIMEOUT))) {
+ err = -ETIMEDOUT;
+ goto error;
+ }
+ }
+
+ return 0;
+error:
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
+ snd_dice_transaction_clear_enable(dice);
+ release_resources(dice);
+ return err;
+}
+
/*
* MEMO: After this function, there're two states of streams:
* - None streams are running.
@@ -293,8 +350,6 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
{
unsigned int curr_rate;
unsigned int i;
- struct reg_params tx_params, rx_params;
- bool need_to_start = false;
enum snd_dice_rate_mode mode;
int err;
@@ -321,7 +376,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
break;
}
if (i < MAX_STREAMS)
- need_to_start = true;
+ goto restart;
/* Check required streams are running or not. */
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
@@ -336,61 +391,11 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
break;
}
if (i < MAX_STREAMS)
- need_to_start = true;
-
- if (need_to_start) {
- err = get_register_params(dice, &tx_params, &rx_params);
- if (err < 0)
- return err;
-
- /* Stop transmission. */
- snd_dice_transaction_clear_enable(dice);
- stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
- stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
- release_resources(dice);
+ goto restart;
- err = ensure_phase_lock(dice);
- if (err < 0) {
- dev_err(&dice->unit->device,
- "fail to ensure phase lock\n");
- goto error;
- }
-
- /* Start both streams. */
- err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
- if (err < 0)
- goto error;
- err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
- if (err < 0)
- goto error;
-
- err = snd_dice_transaction_set_enable(dice);
- if (err < 0) {
- dev_err(&dice->unit->device,
- "fail to enable interface\n");
- goto error;
- }
-
- for (i = 0; i < MAX_STREAMS; i++) {
- if ((i < tx_params.count &&
- !amdtp_stream_wait_callback(&dice->tx_stream[i],
- CALLBACK_TIMEOUT)) ||
- (i < rx_params.count &&
- !amdtp_stream_wait_callback(&dice->rx_stream[i],
- CALLBACK_TIMEOUT))) {
- err = -ETIMEDOUT;
- goto error;
- }
- }
- }
-
- return err;
-error:
- snd_dice_transaction_clear_enable(dice);
- stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
- stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
- release_resources(dice);
- return err;
+ return 0;
+restart:
+ return start_duplex_streams(dice, rate);
}
/*