^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * motu-pcm.c - a part of driver for MOTU FireWire series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "motu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static int motu_rate_constraint(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct snd_motu_packet_format *formats = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct snd_interval rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned int i, pcm_channels, rate, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) rate = snd_motu_clock_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) mode = i / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) pcm_channels = formats->pcm_chunks[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (!snd_interval_test(c, pcm_channels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) rates.min = min(rates.min, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) rates.max = max(rates.max, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return snd_interval_refine(r, &rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int motu_channels_constraint(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct snd_motu_packet_format *formats = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct snd_interval channels = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int i, pcm_channels, rate, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) rate = snd_motu_clock_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) mode = i / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!snd_interval_test(r, rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pcm_channels = formats->pcm_chunks[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) channels.min = min(channels.min, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) channels.max = max(channels.max, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return snd_interval_refine(c, &channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void limit_channels_and_rates(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct snd_pcm_runtime *runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct snd_motu_packet_format *formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct snd_pcm_hardware *hw = &runtime->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int i, pcm_channels, rate, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) hw->channels_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) hw->channels_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) rate = snd_motu_clock_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) mode = i / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pcm_channels = formats->pcm_chunks[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (pcm_channels == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) hw->rates |= snd_pcm_rate_to_rate_bit(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) hw->channels_min = min(hw->channels_min, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) hw->channels_max = max(hw->channels_max, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) snd_pcm_limit_hw_rates(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int init_hw_info(struct snd_motu *motu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct snd_pcm_hardware *hw = &runtime->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_motu_packet_format *formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) hw->formats = SNDRV_PCM_FMTBIT_S32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) stream = &motu->tx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) formats = &motu->tx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) hw->formats = SNDRV_PCM_FMTBIT_S32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) stream = &motu->rx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) formats = &motu->rx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) limit_channels_and_rates(motu, runtime, formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) motu_rate_constraint, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) motu_channels_constraint, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return amdtp_motu_add_pcm_hw_constraints(stream, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct amdtp_domain *d = &motu->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) enum snd_motu_clock_source src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = snd_motu_stream_lock_try(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) mutex_lock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) err = snd_motu_stream_cache_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) err = init_hw_info(motu, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) err = snd_motu_protocol_get_clock_source(motu, &src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) // When source of clock is not internal or any stream is reserved for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) // transmission of PCM frames, the available sampling rate is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) // at current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if ((src != SND_MOTU_CLOCK_SOURCE_INTERNAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) src != SND_MOTU_CLOCK_SOURCE_SPH) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) (motu->substreams_counter > 0 && d->events_per_period > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned int frames_per_period = d->events_per_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned int frames_per_buffer = d->events_per_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) err = snd_motu_protocol_get_clock_rate(motu, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) substream->runtime->hw.rate_min = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) substream->runtime->hw.rate_max = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (frames_per_period > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) frames_per_period, frames_per_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) frames_per_buffer, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) err_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) snd_motu_stream_lock_release(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) snd_motu_stream_lock_release(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned int frames_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned int frames_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) mutex_lock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) err = snd_motu_stream_reserve_duplex(motu, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ++motu->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) mutex_lock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) --motu->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) snd_motu_stream_stop_duplex(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) mutex_lock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) err = snd_motu_stream_start_duplex(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) amdtp_stream_pcm_prepare(&motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mutex_lock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) err = snd_motu_stream_start_duplex(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) mutex_unlock(&motu->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) amdtp_stream_pcm_prepare(&motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) amdtp_stream_pcm_trigger(&motu->tx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) amdtp_stream_pcm_trigger(&motu->tx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) amdtp_stream_pcm_trigger(&motu->rx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) amdtp_stream_pcm_trigger(&motu->rx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int capture_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static int playback_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct snd_motu *motu = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int snd_motu_create_pcm_devices(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static const struct snd_pcm_ops capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .prepare = capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .trigger = capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .pointer = capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .ack = capture_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static const struct snd_pcm_ops playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .prepare = playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .trigger = playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .pointer = playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .ack = playback_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) err = snd_pcm_new(motu->card, motu->card->driver, 0, 1, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pcm->private_data = motu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) strcpy(pcm->name, motu->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }