static int pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_dice *dice = substream->private_data;
+       struct amdtp_domain *d = &dice->domain;
        unsigned int source;
        bool internal;
        int err;
 
        err = snd_dice_stream_lock_try(dice);
        if (err < 0)
-               goto end;
+               return err;
 
        err = init_hw_info(dice, substream);
        if (err < 0)
                break;
        }
 
-       /*
-        * When source of clock is not internal or any PCM streams are running,
-        * available sampling rate is limited at current sampling rate.
-        */
+       mutex_lock(&dice->mutex);
+
+       // When source of clock is not internal or any stream is reserved for
+       // transmission of PCM frames, the available sampling rate is limited
+       // at current one.
        if (!internal ||
-           amdtp_stream_pcm_running(&dice->tx_stream[0]) ||
-           amdtp_stream_pcm_running(&dice->tx_stream[1]) ||
-           amdtp_stream_pcm_running(&dice->rx_stream[0]) ||
-           amdtp_stream_pcm_running(&dice->rx_stream[1])) {
+           (dice->substreams_counter > 0 && d->events_per_period > 0)) {
+               unsigned int frames_per_period = d->events_per_period;
                unsigned int rate;
 
                err = snd_dice_transaction_get_rate(dice, &rate);
-               if (err < 0)
+               if (err < 0) {
+                       mutex_unlock(&dice->mutex);
                        goto err_locked;
+               }
+
                substream->runtime->hw.rate_min = rate;
                substream->runtime->hw.rate_max = rate;
+
+               if (frames_per_period > 0) {
+                       // For double_pcm_frame quirk.
+                       if (rate > 96000)
+                               frames_per_period *= 2;
+
+                       err = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                       SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                       frames_per_period, frames_per_period);
+                       if (err < 0) {
+                               mutex_unlock(&dice->mutex);
+                               goto err_locked;
+                       }
+               }
        }
 
+       mutex_unlock(&dice->mutex);
+
        snd_pcm_set_sync(substream);
-end:
-       return err;
+
+       return 0;
 err_locked:
        snd_dice_stream_lock_release(dice);
        return err;