^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) * dice_pcm.c - a part of driver for DICE 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) * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "dice.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static int dice_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_pcm_substream *substream = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned int index = substream->pcm->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) const struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct snd_interval rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned int *pcm_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int i, rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) pcm_channels = dice->tx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pcm_channels = dice->rx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) rate = snd_dice_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!snd_interval_test(c, pcm_channels[mode]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) rates.min = min(rates.min, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) rates.max = max(rates.max, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return snd_interval_refine(r, &rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int dice_channels_constraint(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct snd_pcm_substream *substream = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int index = substream->pcm->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct snd_interval *r =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct snd_interval *c =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct snd_interval channels = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .min = UINT_MAX, .max = 0, .integer = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int *pcm_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int i, rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) pcm_channels = dice->tx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pcm_channels = dice->rx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rate = snd_dice_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!snd_interval_test(r, rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) channels.min = min(channels.min, pcm_channels[mode]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) channels.max = max(channels.max, pcm_channels[mode]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return snd_interval_refine(c, &channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int limit_channels_and_rates(struct snd_dice *dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct snd_pcm_runtime *runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct snd_pcm_hardware *hw = &runtime->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int *pcm_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (dir == AMDTP_IN_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pcm_channels = dice->tx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pcm_channels = dice->rx_pcm_chs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) hw->channels_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) hw->channels_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int rate, channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) rate = snd_dice_rates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) hw->rates |= snd_pcm_rate_to_rate_bit(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) channels = pcm_channels[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (channels == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) hw->channels_min = min(hw->channels_min, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) hw->channels_max = max(hw->channels_max, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) snd_pcm_limit_hw_rates(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int init_hw_info(struct snd_dice *dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct snd_pcm_hardware *hw = &runtime->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned int index = substream->pcm->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) enum amdtp_stream_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) hw->formats = AM824_IN_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dir = AMDTP_IN_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) stream = &dice->tx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hw->formats = AM824_OUT_PCM_FORMAT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dir = AMDTP_OUT_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) stream = &dice->rx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = limit_channels_and_rates(dice, substream->runtime, dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dice_rate_constraint, substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dice_channels_constraint, substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct amdtp_domain *d = &dice->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bool internal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) err = snd_dice_stream_lock_try(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) err = init_hw_info(dice, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err = snd_dice_transaction_get_clock_source(dice, &source);
^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) switch (source) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) case CLOCK_SOURCE_AES1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case CLOCK_SOURCE_AES2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) case CLOCK_SOURCE_AES3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) case CLOCK_SOURCE_AES4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case CLOCK_SOURCE_AES_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) case CLOCK_SOURCE_ADAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case CLOCK_SOURCE_TDIF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case CLOCK_SOURCE_WC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) internal = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) internal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^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) mutex_lock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) // When source of clock is not internal or any stream is reserved for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) // transmission of PCM frames, the available sampling rate is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) // at current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!internal ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) (dice->substreams_counter > 0 && d->events_per_period > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned int frames_per_period = d->events_per_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned int frames_per_buffer = d->events_per_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) err = snd_dice_transaction_get_rate(dice, &rate);
^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(&dice->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) substream->runtime->hw.rate_min = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) substream->runtime->hw.rate_max = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (frames_per_period > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) // For double_pcm_frame quirk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (rate > 96000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) frames_per_period *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) frames_per_buffer *= 2;
^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) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) frames_per_period, frames_per_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) err = snd_pcm_hw_constraint_minmax(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) frames_per_buffer, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto err_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) err_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) snd_dice_stream_lock_release(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) snd_dice_stream_lock_release(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned int rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) unsigned int events_per_period = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned int events_per_buffer = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) mutex_lock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) // For double_pcm_frame quirk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (rate > 96000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) events_per_period /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) events_per_buffer /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) err = snd_dice_stream_reserve_duplex(dice, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) events_per_period, events_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ++dice->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) mutex_unlock(&dice->mutex);
^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 err;
^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) static int pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mutex_lock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) --dice->substreams_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) snd_dice_stream_stop_duplex(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mutex_lock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) err = snd_dice_stream_start_duplex(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) amdtp_stream_pcm_prepare(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int playback_prepare(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_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mutex_lock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) err = snd_dice_stream_start_duplex(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) mutex_unlock(&dice->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) amdtp_stream_pcm_prepare(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return err;
^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 int capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) amdtp_stream_pcm_trigger(stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) amdtp_stream_pcm_trigger(stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) amdtp_stream_pcm_trigger(stream, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) amdtp_stream_pcm_trigger(stream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static int capture_ack(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct snd_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
^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_ack(&dice->domain, 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 playback_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_dice *dice = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int snd_dice_create_pcm(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static const struct snd_pcm_ops capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .prepare = capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .trigger = capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .pointer = capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .ack = capture_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static const struct snd_pcm_ops playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .open = pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .close = pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .hw_params = pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .hw_free = pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .prepare = playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .trigger = playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .pointer = playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .ack = playback_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) unsigned int capture, playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) for (i = 0; i < MAX_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) capture = playback = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (dice->tx_pcm_chs[i][j] > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) capture = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (dice->rx_pcm_chs[i][j] > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) playback = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pcm->private_data = dice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) strcpy(pcm->name, dice->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (capture > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) &capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (playback > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) &playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }