^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) * oxfw_pcm.c - a part of driver for OXFW970/971 based devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
^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 "oxfw.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) u8 **formats = 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) struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (formats[i] == NULL)
^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) err = snd_oxfw_stream_parse_format(formats[i], &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!snd_interval_test(c, formation.pcm))
^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, formation.rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) t.max = max(t.max, formation.rate);
^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) u8 **formats = 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_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int i, j, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int count, list[SND_OXFW_STREAM_FORMAT_ENTRIES] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (formats[i] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) err = snd_oxfw_stream_parse_format(formats[i], &formation);
^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) if (!snd_interval_test(r, formation.rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (list[count] == formation.pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) for (j = 0; j < ARRAY_SIZE(list); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (list[j] == formation.pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (j == ARRAY_SIZE(list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) list[count] = formation.pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (++count == ARRAY_SIZE(list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return snd_interval_list(c, count, list, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) hw->channels_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) hw->channels_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) hw->rate_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) hw->rate_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) hw->rates = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (formats[i] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) err = snd_oxfw_stream_parse_format(formats[i], &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) hw->channels_min = min(hw->channels_min, formation.pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) hw->channels_max = max(hw->channels_max, formation.pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) hw->rate_min = min(hw->rate_min, formation.rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) hw->rate_max = max(hw->rate_max, formation.rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) hw->rates |= snd_pcm_rate_to_rate_bit(formation.rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int init_hw_params(struct snd_oxfw *oxfw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u8 **formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) stream = &oxfw->tx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) formats = oxfw->tx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) stream = &oxfw->rx_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) formats = oxfw->rx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) limit_channels_and_rates(&runtime->hw, formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) hw_rule_channels, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) hw_rule_rate, formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) err = amdtp_am824_add_pcm_hw_constraints(stream, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int limit_to_current_params(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) enum avc_general_plug_dir dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dir = AVC_GENERAL_PLUG_DIR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dir = AVC_GENERAL_PLUG_DIR_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) substream->runtime->hw.channels_min = formation.pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) substream->runtime->hw.channels_max = formation.pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) substream->runtime->hw.rate_min = formation.rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) substream->runtime->hw.rate_max = formation.rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return err;
^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) static int pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct amdtp_domain *d = &oxfw->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) err = snd_oxfw_stream_lock_try(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err = init_hw_params(oxfw, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) // When source of clock is not internal or any stream is reserved for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) // transmission of PCM frames, the available sampling rate is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) // at current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (oxfw->substreams_count > 0 && d->events_per_period > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int frames_per_period = d->events_per_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int frames_per_buffer = d->events_per_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) err = limit_to_current_params(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (frames_per_period > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) frames_per_period, frames_per_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) frames_per_buffer, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^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) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) err_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) snd_oxfw_stream_lock_release(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) snd_oxfw_stream_lock_release(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned int channels = params_channels(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned int frames_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) unsigned int frames_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rate, channels, frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ++oxfw->substreams_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unsigned int channels = params_channels(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned int frames_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned int frames_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) rate, channels, frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ++oxfw->substreams_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) --oxfw->substreams_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) snd_oxfw_stream_stop_duplex(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) --oxfw->substreams_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) snd_oxfw_stream_stop_duplex(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 0;
^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) static int pcm_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) err = snd_oxfw_stream_start_duplex(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) amdtp_stream_pcm_prepare(&oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int pcm_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) mutex_lock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) err = snd_oxfw_stream_start_duplex(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mutex_unlock(&oxfw->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) amdtp_stream_pcm_prepare(&oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct snd_pcm_substream *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) pcm = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pcm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) amdtp_stream_pcm_trigger(&oxfw->tx_stream, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct snd_pcm_substream *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) pcm = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) pcm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct snd_oxfw *oxfw = sbstm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct snd_oxfw *oxfw = sbstm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int pcm_capture_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int pcm_playback_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct snd_oxfw *oxfw = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static const struct snd_pcm_ops capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .hw_params = pcm_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .hw_free = pcm_capture_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .prepare = pcm_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .trigger = pcm_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .pointer = pcm_capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .ack = pcm_capture_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static const struct snd_pcm_ops playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .hw_params = pcm_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .hw_free = pcm_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .prepare = pcm_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .trigger = pcm_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .pointer = pcm_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .ack = pcm_playback_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) unsigned int cap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) cap = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) err = snd_pcm_new(oxfw->card, oxfw->card->driver, 0, 1, cap, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) pcm->private_data = oxfw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) strcpy(pcm->name, oxfw->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (cap > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }