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);
        }
 
                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);
        }
 
        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);
 
        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);
 
 
        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);
        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)
 
                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;
        amdtp_stream_stop(&ff->rx_stream);
 
        finish_session(ff);
-       release_resources(ff);
 
        return err;
 }
        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)