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>
static int pcm_open(struct snd_pcm_substream *substream)
{
struct snd_tscm *tscm = substream->private_data;
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;
enum snd_tscm_clock clock;
int err;
err = snd_tscm_stream_lock_try(tscm);
if (err < 0)
int err;
err = snd_tscm_stream_lock_try(tscm);
if (err < 0)
err = pcm_init_hw_params(tscm, substream);
if (err < 0)
err = pcm_init_hw_params(tscm, substream);
if (err < 0)
if (err < 0)
goto err_locked;
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);
err = snd_tscm_stream_get_rate(tscm, &rate);
+ if (err < 0) {
+ mutex_unlock(&tscm->mutex);
substream->runtime->hw.rate_min = rate;
substream->runtime->hw.rate_max = rate;
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);
snd_pcm_set_sync(substream);
err_locked:
snd_tscm_stream_lock_release(tscm);
return err;
err_locked:
snd_tscm_stream_lock_release(tscm);
return err;