return err;
 
        mutex_lock(&dg00x->mutex);
-       dg00x->substreams_counter++;
-       err = snd_dg00x_stream_start_duplex(dg00x, 0);
+       err = snd_dg00x_stream_reserve_duplex(dg00x, 0);
+       if (err >= 0) {
+               ++dg00x->substreams_counter;
+               err = snd_dg00x_stream_start_duplex(dg00x);
+       }
        mutex_unlock(&dg00x->mutex);
        if (err < 0)
                snd_dg00x_stream_lock_release(dg00x);
        struct snd_dg00x *dg00x = substream->rmidi->private_data;
 
        mutex_lock(&dg00x->mutex);
-       dg00x->substreams_counter--;
+       --dg00x->substreams_counter;
        snd_dg00x_stream_stop_duplex(dg00x);
+       snd_dg00x_stream_release_duplex(dg00x);
        mutex_unlock(&dg00x->mutex);
 
        snd_dg00x_stream_lock_release(dg00x);
 
                return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+               unsigned int rate = params_rate(hw_params);
+
                mutex_lock(&dg00x->mutex);
-               dg00x->substreams_counter++;
+               err = snd_dg00x_stream_reserve_duplex(dg00x, rate);
+               if (err >= 0)
+                       ++dg00x->substreams_counter;
                mutex_unlock(&dg00x->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 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(&dg00x->mutex);
-               dg00x->substreams_counter++;
+               err = snd_dg00x_stream_reserve_duplex(dg00x, rate);
+               if (err >= 0)
+                       ++dg00x->substreams_counter;
                mutex_unlock(&dg00x->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
        mutex_lock(&dg00x->mutex);
 
        if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
-               dg00x->substreams_counter--;
+               --dg00x->substreams_counter;
 
        snd_dg00x_stream_stop_duplex(dg00x);
+       snd_dg00x_stream_release_duplex(dg00x);
 
        mutex_unlock(&dg00x->mutex);
 
        mutex_lock(&dg00x->mutex);
 
        if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
-               dg00x->substreams_counter--;
+               --dg00x->substreams_counter;
 
        snd_dg00x_stream_stop_duplex(dg00x);
+       snd_dg00x_stream_release_duplex(dg00x);
 
        mutex_unlock(&dg00x->mutex);
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_dg00x *dg00x = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        mutex_lock(&dg00x->mutex);
 
-       err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate);
+       err = snd_dg00x_stream_start_duplex(dg00x);
        if (err >= 0)
                amdtp_stream_pcm_prepare(&dg00x->tx_stream);
 
 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_dg00x *dg00x = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        mutex_lock(&dg00x->mutex);
 
-       err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate);
+       err = snd_dg00x_stream_start_duplex(dg00x);
        if (err >= 0) {
                amdtp_stream_pcm_prepare(&dg00x->rx_stream);
                amdtp_dot_reset(&dg00x->rx_stream);
 
        return err;
 }
 
-static void release_resources(struct snd_dg00x *dg00x)
-{
-       /* Release isochronous resources. */
-       fw_iso_resources_free(&dg00x->tx_resources);
-       fw_iso_resources_free(&dg00x->rx_resources);
-}
-
 static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
                          unsigned int rate)
 {
        fw_iso_resources_destroy(&dg00x->tx_resources);
 }
 
-int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate)
+int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate)
 {
        unsigned int curr_rate;
-       int err = 0;
-
-       if (dg00x->substreams_counter == 0)
-               goto end;
+       int err;
 
-       /* Check current sampling rate. */
        err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
        if (err < 0)
-               goto error;
+               return err;
        if (rate == 0)
                rate = curr_rate;
-       if (curr_rate != rate ||
-           amdtp_streaming_error(&dg00x->tx_stream) ||
-           amdtp_streaming_error(&dg00x->rx_stream)) {
+
+       if (dg00x->substreams_counter == 0 || curr_rate != rate) {
                finish_session(dg00x);
 
-               release_resources(dg00x);
-       }
+               fw_iso_resources_free(&dg00x->tx_resources);
+               fw_iso_resources_free(&dg00x->rx_resources);
 
-       /*
-        * No packets are transmitted without receiving packets, reagardless of
-        * which source of clock is used.
-        */
-       if (!amdtp_stream_running(&dg00x->rx_stream)) {
                err = snd_dg00x_stream_set_local_rate(dg00x, rate);
                if (err < 0)
-                       goto error;
+                       return err;
 
                err = keep_resources(dg00x, &dg00x->rx_stream, rate);
                if (err < 0)
-                       goto error;
+                       return err;
 
                err = keep_resources(dg00x, &dg00x->tx_stream, rate);
-               if (err < 0)
-                       goto error;
+               if (err < 0) {
+                       fw_iso_resources_free(&dg00x->rx_resources);
+                       return err;
+               }
+       }
+
+       return 0;
+}
 
+void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x)
+{
+       if (dg00x->substreams_counter == 0) {
+               fw_iso_resources_free(&dg00x->tx_resources);
+               fw_iso_resources_free(&dg00x->rx_resources);
+       }
+}
+
+int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
+{
+       int err = 0;
+
+       if (dg00x->substreams_counter == 0)
+               return 0;
+
+       if (amdtp_streaming_error(&dg00x->tx_stream) ||
+           amdtp_streaming_error(&dg00x->rx_stream))
+               finish_session(dg00x);
+
+       /*
+        * No packets are transmitted without receiving packets, reagardless of
+        * which source of clock is used.
+        */
+       if (!amdtp_stream_running(&dg00x->rx_stream)) {
                err = begin_session(dg00x);
                if (err < 0)
                        goto error;
                        goto error;
                }
        }
-end:
-       return err;
+
+       return 0;
 error:
        finish_session(dg00x);
 
-       release_resources(dg00x);
-
        return err;
 }
 
 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
 {
-       if (dg00x->substreams_counter > 0)
-               return;
-
-       finish_session(dg00x);
-       release_resources(dg00x);
+       if (dg00x->substreams_counter == 0)
+               finish_session(dg00x);
 }
 
 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)
 
 int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x,
                                          bool *detect);
 int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x);
-int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate);
+int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate);
+int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x);
 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x);
+void snd_dg00x_stream_release_duplex(struct snd_dg00x *dg00x);
 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x);
 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x);