ALSA: firewire-digi00x: use the same size of period for PCM substream in AMDTP streams
[linux-2.6-block.git] / sound / firewire / digi00x / digi00x-pcm.c
index 9ced309d61facb9824fc3e0d49ad119e012110a8..8dbfb3ff17f6b098b446c1228de03930f8beeabc 100644 (file)
@@ -100,14 +100,14 @@ static int pcm_init_hw_params(struct snd_dg00x *dg00x,
 static int pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_dg00x *dg00x = substream->private_data;
+       struct amdtp_domain *d = &dg00x->domain;
        enum snd_dg00x_clock clock;
        bool detect;
-       unsigned int rate;
        int err;
 
        err = snd_dg00x_stream_lock_try(dg00x);
        if (err < 0)
-               goto end;
+               return err;
 
        err = pcm_init_hw_params(dg00x, substream);
        if (err < 0)
@@ -127,19 +127,40 @@ static int pcm_open(struct snd_pcm_substream *substream)
                }
        }
 
+       mutex_lock(&dg00x->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 ((clock != SND_DG00X_CLOCK_INTERNAL) ||
-           amdtp_stream_pcm_running(&dg00x->rx_stream) ||
-           amdtp_stream_pcm_running(&dg00x->tx_stream)) {
+           (dg00x->substreams_counter > 0 && d->events_per_period > 0)) {
+               unsigned int frames_per_period = d->events_per_period;
+               unsigned int rate;
+
                err = snd_dg00x_stream_get_external_rate(dg00x, &rate);
-               if (err < 0)
+               if (err < 0) {
+                       mutex_unlock(&dg00x->mutex);
                        goto err_locked;
+               }
                substream->runtime->hw.rate_min = rate;
                substream->runtime->hw.rate_max = rate;
+
+               if (frames_per_period > 0) {
+                       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(&dg00x->mutex);
+                               goto err_locked;
+                       }
+               }
        }
 
+       mutex_unlock(&dg00x->mutex);
+
        snd_pcm_set_sync(substream);
-end:
-       return err;
+
+       return 0;
 err_locked:
        snd_dg00x_stream_lock_release(dg00x);
        return err;