ALSA: firewire-tascam: use the same size of period for PCM substream in AMDTP streams
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 7 Oct 2019 11:05:30 +0000 (20:05 +0900)
committerTakashi Iwai <tiwai@suse.de>
Thu, 17 Oct 2019 10:02:46 +0000 (12:02 +0200)
In current implementation, when opening a PCM substream, it's needed to
check whether the opposite PCM substream runs. This is to assign
effectual constraints (e.g. sampling rate) to opened PCM substream.

The number of PCM substreams on AMDTP streams in domain is recorded in
own structure. Usage of this count is an alternative of the above check.
This is better because the count is incremented in pcm.hw_params earlier
than pcm.trigger.

This commit replaces the check with the substream count and the value for
the size of PCM period. Unlike the other drivers in ALSA firewire stack,
no MIDI substream is multiplexed into AMDTP stream.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20191007110532.30270-16-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/tascam/tascam-pcm.c

index cea26d5eff1a5898499b12a05f30a0b49234334b..6cd3a420fbdf249aa10975ea122a087ac6798970 100644 (file)
@@ -43,13 +43,13 @@ static int pcm_init_hw_params(struct snd_tscm *tscm,
 static int pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_tscm *tscm = substream->private_data;
+       struct amdtp_domain *d = &tscm->domain;
        enum snd_tscm_clock clock;
-       unsigned int rate;
        int err;
 
        err = snd_tscm_stream_lock_try(tscm);
        if (err < 0)
-               goto end;
+               return err;
 
        err = pcm_init_hw_params(tscm, substream);
        if (err < 0)
@@ -59,19 +59,37 @@ static int pcm_open(struct snd_pcm_substream *substream)
        if (err < 0)
                goto err_locked;
 
-       if (clock != SND_TSCM_CLOCK_INTERNAL ||
-           amdtp_stream_pcm_running(&tscm->rx_stream) ||
-           amdtp_stream_pcm_running(&tscm->tx_stream)) {
+       mutex_lock(&tscm->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_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) {
+               unsigned int frames_per_period = d->events_per_period;
+               unsigned int rate;
+
                err = snd_tscm_stream_get_rate(tscm, &rate);
-               if (err < 0)
+               if (err < 0) {
+                       mutex_unlock(&tscm->mutex);
                        goto err_locked;
+               }
                substream->runtime->hw.rate_min = rate;
                substream->runtime->hw.rate_max = rate;
+
+               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(&tscm->mutex);
+                       goto err_locked;
+               }
        }
 
+       mutex_unlock(&tscm->mutex);
+
        snd_pcm_set_sync(substream);
-end:
-       return err;
+
+       return 0;
 err_locked:
        snd_tscm_stream_lock_release(tscm);
        return err;