^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) * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014-2015 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 "digi00x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define CALLBACK_TIMEOUT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) [SND_DG00X_RATE_44100] = 44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) [SND_DG00X_RATE_48000] = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) [SND_DG00X_RATE_88200] = 88200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) [SND_DG00X_RATE_96000] = 96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Multi Bit Linear Audio data channels for each sampling transfer frequency. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) const unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) snd_dg00x_stream_pcm_channels[SND_DG00X_RATE_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Analog/ADAT/SPDIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) [SND_DG00X_RATE_44100] = (8 + 8 + 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) [SND_DG00X_RATE_48000] = (8 + 8 + 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Analog/SPDIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [SND_DG00X_RATE_88200] = (8 + 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) [SND_DG00X_RATE_96000] = (8 + 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int snd_dg00x_stream_get_local_rate(struct snd_dg00x *dg00x, unsigned int *rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ®, sizeof(reg), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) data = be32_to_cpu(reg) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *rate = snd_dg00x_stream_rates[data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int snd_dg00x_stream_set_local_rate(struct snd_dg00x *dg00x, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) for (i = 0; i < ARRAY_SIZE(snd_dg00x_stream_rates); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (rate == snd_dg00x_stream_rates[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (i == ARRAY_SIZE(snd_dg00x_stream_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) reg = cpu_to_be32(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ®, sizeof(reg), 0);
^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) int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) enum snd_dg00x_clock *clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) DG00X_ADDR_BASE + DG00X_OFFSET_CLOCK_SOURCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ®, sizeof(reg), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *clock = be32_to_cpu(reg) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (*clock >= SND_DG00X_CLOCK_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) DG00X_ADDR_BASE + DG00X_OFFSET_DETECT_EXTERNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ®, sizeof(reg), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *detect = be32_to_cpu(reg) > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int *rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) DG00X_ADDR_BASE + DG00X_OFFSET_EXTERNAL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ®, sizeof(reg), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) data = be32_to_cpu(reg) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *rate = snd_dg00x_stream_rates[data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* This means desync. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return err;
^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 void finish_session(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) __be32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) data = cpu_to_be32(0x00000003);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) &data, sizeof(data), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) // Unregister isochronous channels for both direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) &data, sizeof(data), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) // Just after finishing the session, the device may lost transmitting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) // functionality for a short time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) msleep(50);
^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) static int begin_session(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) __be32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) // Register isochronous channels for both direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dg00x->rx_resources.channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) &data, sizeof(data), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) &data, sizeof(data), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) curr = be32_to_cpu(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (curr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) curr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) curr--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) while (curr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) data = cpu_to_be32(curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) err = snd_fw_transaction(dg00x->unit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) TCODE_WRITE_QUADLET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) DG00X_ADDR_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) DG00X_OFFSET_STREAMING_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) &data, sizeof(data), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) curr--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) // Check sampling rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (snd_dg00x_stream_rates[i] == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (i == SND_DG00X_RATE_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (stream == &dg00x->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) resources = &dg00x->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) resources = &dg00x->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err = amdtp_dot_set_parameters(stream, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) snd_dg00x_stream_pcm_channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return fw_iso_resources_allocate(resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) amdtp_stream_get_max_payload(stream),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) fw_parent_device(dg00x->unit)->max_speed);
^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 init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) enum amdtp_stream_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (s == &dg00x->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) resources = &dg00x->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) dir = AMDTP_IN_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) resources = &dg00x->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dir = AMDTP_OUT_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) err = fw_iso_resources_init(resources, dg00x->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) err = amdtp_dot_init(s, dg00x->unit, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) fw_iso_resources_destroy(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return err;
^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) static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) amdtp_stream_destroy(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (s == &dg00x->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) fw_iso_resources_destroy(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) fw_iso_resources_destroy(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err = init_stream(dg00x, &dg00x->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (err < 0)
^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) err = init_stream(dg00x, &dg00x->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) destroy_stream(dg00x, &dg00x->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) err = amdtp_domain_init(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) destroy_stream(dg00x, &dg00x->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) destroy_stream(dg00x, &dg00x->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * This function should be called before starting streams or after stopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) amdtp_domain_destroy(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) destroy_stream(dg00x, &dg00x->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) destroy_stream(dg00x, &dg00x->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned int frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned int frames_per_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) unsigned int curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) rate = curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (dg00x->substreams_counter == 0 || curr_rate != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) amdtp_domain_stop(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) finish_session(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) fw_iso_resources_free(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) fw_iso_resources_free(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err = snd_dg00x_stream_set_local_rate(dg00x, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) err = keep_resources(dg00x, &dg00x->rx_stream, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) err = keep_resources(dg00x, &dg00x->tx_stream, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) fw_iso_resources_free(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err = amdtp_domain_set_events_per_period(&dg00x->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) fw_iso_resources_free(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) fw_iso_resources_free(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^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) int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) unsigned int generation = dg00x->rx_resources.generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (dg00x->substreams_counter == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (amdtp_streaming_error(&dg00x->tx_stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) amdtp_streaming_error(&dg00x->rx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) amdtp_domain_stop(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) finish_session(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (generation != fw_parent_device(dg00x->unit)->card->generation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = fw_iso_resources_update(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) err = fw_iso_resources_update(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * No packets are transmitted without receiving packets, reagardless of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * which source of clock is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (!amdtp_stream_running(&dg00x->rx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int spd = fw_parent_device(dg00x->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err = begin_session(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dg00x->rx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) dg00x->tx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) err = amdtp_domain_start(&dg00x->domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) CALLBACK_TIMEOUT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) !amdtp_stream_wait_callback(&dg00x->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) CALLBACK_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) amdtp_domain_stop(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) finish_session(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (dg00x->substreams_counter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) amdtp_domain_stop(&dg00x->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) finish_session(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) fw_iso_resources_free(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) fw_iso_resources_free(&dg00x->rx_resources);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) fw_iso_resources_update(&dg00x->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) fw_iso_resources_update(&dg00x->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) amdtp_stream_update(&dg00x->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) amdtp_stream_update(&dg00x->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dg00x->dev_lock_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) wake_up(&dg00x->hwdep_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) spin_lock_irq(&dg00x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* user land lock this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (dg00x->dev_lock_count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* this is the first time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (dg00x->dev_lock_count++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) snd_dg00x_stream_lock_changed(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) spin_unlock_irq(&dg00x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) spin_lock_irq(&dg00x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (WARN_ON(dg00x->dev_lock_count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (--dg00x->dev_lock_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) snd_dg00x_stream_lock_changed(dg00x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) spin_unlock_irq(&dg00x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }