summaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/fireface/ff-pcm.c18
-rw-r--r--sound/firewire/fireface/ff-stream.c67
-rw-r--r--sound/firewire/fireface/ff.h2
3 files changed, 57 insertions, 30 deletions
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c
index 5adf04b95c04..53477404a58f 100644
--- a/sound/firewire/fireface/ff-pcm.c
+++ b/sound/firewire/fireface/ff-pcm.c
@@ -211,8 +211,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&ff->mutex);
- ff->substreams_counter++;
+ err = snd_ff_stream_reserve_duplex(ff, rate);
+ if (err >= 0)
+ ++ff->substreams_counter;
mutex_unlock(&ff->mutex);
}
@@ -231,8 +235,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&ff->mutex);
- ff->substreams_counter++;
+ err = snd_ff_stream_reserve_duplex(ff, rate);
+ if (err >= 0)
+ ++ff->substreams_counter;
mutex_unlock(&ff->mutex);
}
@@ -246,9 +254,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&ff->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- ff->substreams_counter--;
+ --ff->substreams_counter;
snd_ff_stream_stop_duplex(ff);
+ snd_ff_stream_release_duplex(ff);
mutex_unlock(&ff->mutex);
@@ -262,9 +271,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&ff->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- ff->substreams_counter--;
+ --ff->substreams_counter;
snd_ff_stream_stop_duplex(ff);
+ snd_ff_stream_release_duplex(ff);
mutex_unlock(&ff->mutex);
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index 740963e4e1c9..d9d1b469a8e9 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -31,12 +31,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
return 0;
}
-static void release_resources(struct snd_ff *ff)
-{
- fw_iso_resources_free(&ff->tx_resources);
- fw_iso_resources_free(&ff->rx_resources);
-}
-
static inline void finish_session(struct snd_ff *ff)
{
ff->spec->protocol->finish_session(ff);
@@ -104,36 +98,27 @@ void snd_ff_stream_destroy_duplex(struct snd_ff *ff)
destroy_stream(ff, AMDTP_OUT_STREAM);
}
-int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
+int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate)
{
unsigned int curr_rate;
enum snd_ff_clock_src src;
int err;
- if (ff->substreams_counter == 0)
- return 0;
-
err = ff->spec->protocol->get_clock(ff, &curr_rate, &src);
if (err < 0)
return err;
- if (curr_rate != rate ||
- amdtp_streaming_error(&ff->tx_stream) ||
- amdtp_streaming_error(&ff->rx_stream)) {
- finish_session(ff);
+
+ if (ff->substreams_counter == 0 || curr_rate != rate) {
+ enum snd_ff_stream_mode mode;
+ int i;
amdtp_stream_stop(&ff->tx_stream);
amdtp_stream_stop(&ff->rx_stream);
- release_resources(ff);
- }
+ finish_session(ff);
- /*
- * Regardless of current source of clock signal, drivers transfer some
- * packets. Then, the device transfers packets.
- */
- if (!amdtp_stream_running(&ff->rx_stream)) {
- enum snd_ff_stream_mode mode;
- int i;
+ fw_iso_resources_free(&ff->tx_resources);
+ fw_iso_resources_free(&ff->rx_resources);
for (i = 0; i < CIP_SFC_COUNT; ++i) {
if (amdtp_rate_table[i] == rate)
@@ -158,8 +143,40 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
err = ff->spec->protocol->allocate_resources(ff, rate);
if (err < 0)
- goto error;
+ return err;
+ }
+
+ return 0;
+}
+
+void snd_ff_stream_release_duplex(struct snd_ff *ff)
+{
+ if (ff->substreams_counter == 0) {
+ fw_iso_resources_free(&ff->tx_resources);
+ fw_iso_resources_free(&ff->rx_resources);
+ }
+}
+
+int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
+{
+ int err;
+
+ if (ff->substreams_counter == 0)
+ return 0;
+ if (amdtp_streaming_error(&ff->tx_stream) ||
+ amdtp_streaming_error(&ff->rx_stream)) {
+ amdtp_stream_stop(&ff->tx_stream);
+ amdtp_stream_stop(&ff->rx_stream);
+
+ finish_session(ff);
+ }
+
+ /*
+ * Regardless of current source of clock signal, drivers transfer some
+ * packets. Then, the device transfers packets.
+ */
+ if (!amdtp_stream_running(&ff->rx_stream)) {
err = ff->spec->protocol->begin_session(ff, rate);
if (err < 0)
goto error;
@@ -201,7 +218,6 @@ error:
amdtp_stream_stop(&ff->rx_stream);
finish_session(ff);
- release_resources(ff);
return err;
}
@@ -214,7 +230,6 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff)
amdtp_stream_stop(&ff->tx_stream);
amdtp_stream_stop(&ff->rx_stream);
finish_session(ff);
- release_resources(ff);
}
void snd_ff_stream_update_duplex(struct snd_ff *ff)
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index c478103388a2..fe5739ee1c88 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -138,6 +138,8 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
enum snd_ff_stream_mode *mode);
int snd_ff_stream_init_duplex(struct snd_ff *ff);
void snd_ff_stream_destroy_duplex(struct snd_ff *ff);
+int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate);
+void snd_ff_stream_release_duplex(struct snd_ff *ff);
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate);
void snd_ff_stream_stop_duplex(struct snd_ff *ff);
void snd_ff_stream_update_duplex(struct snd_ff *ff);