@@ -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;
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> --- sound/firewire/tascam/tascam-pcm.c | 34 +++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-)