^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) * ff-pcm.c - a part of driver for RME Fireface 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
^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 "ff.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static int hw_rule_rate(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) const unsigned int *pcm_channels = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
^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 t = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) enum snd_ff_stream_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) err = snd_ff_stream_get_multiplier_mode(i, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!snd_interval_test(c, pcm_channels[mode]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) t.min = min(t.min, amdtp_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) t.max = max(t.max, amdtp_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return snd_interval_refine(r, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int hw_rule_channels(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const unsigned int *pcm_channels = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct snd_interval t = {
^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;
^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(amdtp_rate_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) enum snd_ff_stream_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) err = snd_ff_stream_get_multiplier_mode(i, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!snd_interval_test(r, amdtp_rate_table[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) t.min = min(t.min, pcm_channels[mode]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) t.max = max(t.max, pcm_channels[mode]);
^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) return snd_interval_refine(c, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const unsigned int *pcm_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int rate, channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) hw->channels_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) hw->channels_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) hw->rate_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) hw->rate_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) enum snd_ff_stream_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) err = snd_ff_stream_get_multiplier_mode(i, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) channels = pcm_channels[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (pcm_channels[mode] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) hw->channels_min = min(hw->channels_min, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) hw->channels_max = max(hw->channels_max, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) rate = amdtp_rate_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) hw->rates |= snd_pcm_rate_to_rate_bit(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) hw->rate_min = min(hw->rate_min, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) hw->rate_max = max(hw->rate_max, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int pcm_init_hw_params(struct snd_ff *ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct amdtp_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const unsigned int *pcm_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) s = &ff->tx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pcm_channels = ff->spec->pcm_capture_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) s = &ff->rx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pcm_channels = ff->spec->pcm_playback_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) limit_channels_and_rates(&runtime->hw, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) hw_rule_channels, (void *)pcm_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) hw_rule_rate, (void *)pcm_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return amdtp_ff_add_pcm_hw_constraints(s, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct amdtp_domain *d = &ff->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) enum snd_ff_clock_src src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) err = snd_ff_stream_lock_try(ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) err = pcm_init_hw_params(ff, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto release_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) err = ff->spec->protocol->get_clock(ff, &rate, &src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) goto release_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) mutex_lock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) // When source of clock is not internal or any stream is reserved for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) // transmission of PCM frames, the available sampling rate is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) // at current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (src != SND_FF_CLOCK_SRC_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i < CIP_SFC_COUNT; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (amdtp_rate_table[i] == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) // The unit is configured at sampling frequency which packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) // streaming engine can't support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (i >= CIP_SFC_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) goto release_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) substream->runtime->hw.rate_min = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) substream->runtime->hw.rate_max = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (ff->substreams_counter > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int frames_per_period = d->events_per_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned int frames_per_buffer = d->events_per_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rate = amdtp_rate_table[ff->rx_stream.sfc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) substream->runtime->hw.rate_min = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) substream->runtime->hw.rate_max = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) frames_per_period, frames_per_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) goto release_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) frames_per_buffer, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) goto release_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^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) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) release_lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) snd_ff_stream_lock_release(ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) snd_ff_stream_lock_release(ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned int frames_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned int frames_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mutex_lock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ++ff->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) mutex_lock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) --ff->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) snd_ff_stream_stop_duplex(ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int pcm_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mutex_lock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err = snd_ff_stream_start_duplex(ff, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) amdtp_stream_pcm_prepare(&ff->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int pcm_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mutex_lock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) err = snd_ff_stream_start_duplex(ff, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) amdtp_stream_pcm_prepare(&ff->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mutex_unlock(&ff->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) amdtp_stream_pcm_trigger(&ff->tx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) amdtp_stream_pcm_trigger(&ff->tx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) amdtp_stream_pcm_trigger(&ff->rx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) amdtp_stream_pcm_trigger(&ff->rx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct snd_ff *ff = sbstrm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct snd_ff *ff = sbstrm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int pcm_capture_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int pcm_playback_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct snd_ff *ff = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int snd_ff_create_pcm_devices(struct snd_ff *ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static const struct snd_pcm_ops pcm_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .prepare = pcm_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .trigger = pcm_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .pointer = pcm_capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .ack = pcm_capture_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static const struct snd_pcm_ops pcm_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .prepare = pcm_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .trigger = pcm_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .pointer = pcm_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .ack = pcm_playback_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) pcm->private_data = ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) snprintf(pcm->name, sizeof(pcm->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) "%s PCM", ff->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }