^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) * bebob_pcm.c - a part of driver for BeBoB based devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2013-2014 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 "./bebob.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) hw_rule_rate(struct snd_pcm_hw_params *params, 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) struct snd_bebob_stream_formation *formations = 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 < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* entry is invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (formations[i].pcm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!snd_interval_test(c, formations[i].pcm))
^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) t.min = min(t.min, snd_bebob_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) t.max = max(t.max, snd_bebob_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return snd_interval_refine(r, &t);
^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) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct snd_bebob_stream_formation *formations = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct snd_interval t = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* entry is invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (formations[i].pcm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!snd_interval_test(r, snd_bebob_rate_table[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) t.min = min(t.min, formations[i].pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) t.max = max(t.max, formations[i].pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return snd_interval_refine(c, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) limit_channels_and_rates(struct snd_pcm_hardware *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct snd_bebob_stream_formation *formations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) hw->channels_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) hw->channels_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) hw->rate_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) hw->rate_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) hw->rates = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* entry has no PCM channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (formations[i].pcm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) hw->channels_min = min(hw->channels_min, formations[i].pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) hw->channels_max = max(hw->channels_max, formations[i].pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) hw->rate_min = min(hw->rate_min, snd_bebob_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) hw->rate_max = max(hw->rate_max, snd_bebob_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) hw->rates |= snd_pcm_rate_to_rate_bit(snd_bebob_rate_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pcm_init_hw_params(struct snd_bebob *bebob,
^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 amdtp_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct snd_bebob_stream_formation *formations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) s = &bebob->tx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) formations = bebob->tx_stream_formations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) s = &bebob->rx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) formations = bebob->rx_stream_formations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) limit_channels_and_rates(&runtime->hw, formations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) hw_rule_channels, formations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) hw_rule_rate, formations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) err = amdtp_am824_add_pcm_hw_constraints(s, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const struct snd_bebob_rate_spec *spec = bebob->spec->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct amdtp_domain *d = &bebob->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) enum snd_bebob_clock_type src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err = snd_bebob_stream_lock_try(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) err = pcm_init_hw_params(bebob, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) err = snd_bebob_stream_get_clock_src(bebob, &src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mutex_lock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) // When source of clock is not internal or any stream is reserved for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) // transmission of PCM frames, the available sampling rate is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) // at current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) (bebob->substreams_counter > 0 && d->events_per_period > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int frames_per_period = d->events_per_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned int frames_per_buffer = d->events_per_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned int sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) err = spec->get(bebob, &sampling_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dev_err(&bebob->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) "fail to get sampling rate: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) substream->runtime->hw.rate_min = sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) substream->runtime->hw.rate_max = sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (frames_per_period > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) frames_per_period, frames_per_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) frames_per_buffer, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) err_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) snd_bebob_stream_lock_release(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) snd_bebob_stream_lock_release(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned int frames_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned int frames_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mutex_lock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) err = snd_bebob_stream_reserve_duplex(bebob, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ++bebob->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) mutex_lock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) bebob->substreams_counter--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) snd_bebob_stream_stop_duplex(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mutex_unlock(&bebob->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) pcm_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) err = snd_bebob_stream_start_duplex(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) amdtp_stream_pcm_prepare(&bebob->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pcm_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) err = snd_bebob_stream_start_duplex(bebob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) amdtp_stream_pcm_prepare(&bebob->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) amdtp_stream_pcm_trigger(&bebob->tx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) amdtp_stream_pcm_trigger(&bebob->tx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) amdtp_stream_pcm_trigger(&bebob->rx_stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) amdtp_stream_pcm_trigger(&bebob->rx_stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct snd_bebob *bebob = sbstrm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return amdtp_domain_stream_pcm_pointer(&bebob->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) &bebob->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct snd_bebob *bebob = sbstrm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return amdtp_domain_stream_pcm_pointer(&bebob->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) &bebob->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int pcm_capture_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return amdtp_domain_stream_pcm_ack(&bebob->domain, &bebob->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int pcm_playback_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct snd_bebob *bebob = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return amdtp_domain_stream_pcm_ack(&bebob->domain, &bebob->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static const struct snd_pcm_ops capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .prepare = pcm_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .trigger = pcm_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .pointer = pcm_capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .ack = pcm_capture_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static const struct snd_pcm_ops playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .prepare = pcm_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .trigger = pcm_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .pointer = pcm_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .ack = pcm_playback_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) err = snd_pcm_new(bebob->card, bebob->card->driver, 0, 1, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) pcm->private_data = bebob;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) snprintf(pcm->name, sizeof(pcm->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "%s PCM", bebob->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }