^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_stream.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) #define CALLBACK_TIMEOUT 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct reg_params {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned int size;
^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) const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* mode 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) [0] = 32000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) [1] = 44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) [2] = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* mode 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [3] = 88200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [4] = 96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* mode 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) [5] = 176400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) [6] = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) enum snd_dice_rate_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Corresponding to each entry in snd_dice_rates. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static const enum snd_dice_rate_mode modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) [0] = SND_DICE_RATE_MODE_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) [1] = SND_DICE_RATE_MODE_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) [2] = SND_DICE_RATE_MODE_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) [3] = SND_DICE_RATE_MODE_MIDDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) [4] = SND_DICE_RATE_MODE_MIDDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) [5] = SND_DICE_RATE_MODE_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) [6] = SND_DICE_RATE_MODE_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!(dice->clock_caps & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (snd_dice_rates[i] != rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *mode = modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * to GLOBAL_STATUS. Especially, just after powering on, these are different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) __be32 reg, nominal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data &= ~CLOCK_RATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (snd_dice_rates[i] == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (i == ARRAY_SIZE(snd_dice_rates))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) data |= i << CLOCK_RATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (completion_done(&dice->clock_accepted))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) reinit_completion(&dice->clock_accepted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (wait_for_completion_timeout(&dice->clock_accepted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Old versions of Dice firmware transfer no notification when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * the same clock status as current one is set. In this case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * just check current clock status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) &nominal, sizeof(nominal));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int get_register_params(struct snd_dice *dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct reg_params *tx_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct reg_params *rx_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) __be32 reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) tx_params->count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) tx_params->size = be32_to_cpu(reg[1]) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) rx_params->count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rx_params->size = be32_to_cpu(reg[1]) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void release_resources(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) for (i = 0; i < MAX_STREAMS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fw_iso_resources_free(&dice->tx_resources[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fw_iso_resources_free(&dice->rx_resources[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct reg_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (i = 0; i < params->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) reg = cpu_to_be32((u32)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) snd_dice_transaction_write_tx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) params->size * i + TX_ISOCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) snd_dice_transaction_write_rx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) params->size * i + RX_ISOCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct fw_iso_resources *resources, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned int pcm_chs, unsigned int midi_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bool double_pcm_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int i;
^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) // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) // one data block of AMDTP packet. Thus sampling transfer frequency is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) // transferred on AMDTP packets at 96 kHz. Two successive samples of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) // channel are stored consecutively in the packet. This quirk is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) // as 'Dual Wire'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) // For this quirk, blocking mode is required and PCM buffer size should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) // be aligned to SYT_INTERVAL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) double_pcm_frames = rate > 96000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (double_pcm_frames) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) rate /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pcm_chs *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) double_pcm_frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (double_pcm_frames) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pcm_chs /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i < pcm_chs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) amdtp_am824_set_pcm_position(stream, i, i * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) amdtp_am824_set_pcm_position(stream, i + pcm_chs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) i * 2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return fw_iso_resources_allocate(resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) amdtp_stream_get_max_payload(stream),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) fw_parent_device(dice->unit)->max_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct reg_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) for (i = 0; i < params->count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) __be32 reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) unsigned int pcm_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) unsigned int pcm_chs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned int midi_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) stream = &dice->tx_stream[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) resources = &dice->tx_resources[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pcm_cache = dice->tx_pcm_chs[i][mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) err = snd_dice_transaction_read_tx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) params->size * i + TX_NUMBER_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) stream = &dice->rx_stream[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) resources = &dice->rx_resources[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) pcm_cache = dice->rx_pcm_chs[i][mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) err = snd_dice_transaction_read_rx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) params->size * i + RX_NUMBER_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pcm_chs = be32_to_cpu(reg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) midi_ports = be32_to_cpu(reg[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) // These are important for developer of this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (pcm_chs != pcm_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) dev_info(&dice->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) "cache mismatch: pcm: %u:%u, midi: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) pcm_chs, pcm_cache, midi_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) err = keep_resources(dice, stream, resources, rate, pcm_chs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) midi_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct reg_params *rx_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) stop_streams(dice, AMDTP_IN_STREAM, tx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) snd_dice_transaction_clear_enable(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unsigned int events_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) unsigned int events_per_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) unsigned int curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) // Check sampling transmission frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) err = snd_dice_transaction_get_rate(dice, &curr_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) rate = curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (dice->substreams_counter == 0 || curr_rate != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct reg_params tx_params, rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) amdtp_domain_stop(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) err = get_register_params(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) finish_session(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) release_resources(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) // Just after owning the unit (GLOBAL_OWNER), the unit can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) // return invalid stream formats. Selecting clock parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) // have an effect for the unit to refine it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err = ensure_phase_lock(dice, 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) // After changing sampling transfer frequency, the value of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) // register can be changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) err = get_register_params(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) &tx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) err = amdtp_domain_set_events_per_period(&dice->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) events_per_period, events_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) goto error;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) release_resources(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) unsigned int rate, struct reg_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) for (i = 0; i < params->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) stream = dice->tx_stream + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) resources = dice->tx_resources + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) stream = dice->rx_stream + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) resources = dice->rx_resources + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) reg = cpu_to_be32(resources->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) err = snd_dice_transaction_write_tx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) params->size * i + TX_ISOCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) err = snd_dice_transaction_write_rx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) params->size * i + RX_ISOCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) reg = cpu_to_be32(max_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) err = snd_dice_transaction_write_tx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) params->size * i + TX_SPEED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ®, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err = amdtp_domain_add_stream(&dice->domain, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) resources->channel, max_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return err;
^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) return 0;
^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) * MEMO: After this function, there're two states of streams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * - None streams are running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * - All streams are running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int snd_dice_stream_start_duplex(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) unsigned int generation = dice->rx_resources[0].generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct reg_params tx_params, rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (dice->substreams_counter == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) err = get_register_params(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) // Check error of packet streaming.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) for (i = 0; i < MAX_STREAMS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (amdtp_streaming_error(&dice->tx_stream[i]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) amdtp_streaming_error(&dice->rx_stream[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) amdtp_domain_stop(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) finish_session(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (generation != fw_parent_device(dice->unit)->card->generation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) for (i = 0; i < MAX_STREAMS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (i < tx_params.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) fw_iso_resources_update(dice->tx_resources + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (i < rx_params.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) fw_iso_resources_update(dice->rx_resources + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) // Check required streams are running or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) err = snd_dice_transaction_get_rate(dice, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) for (i = 0; i < MAX_STREAMS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (dice->tx_pcm_chs[i][mode] > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) !amdtp_stream_running(&dice->tx_stream[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (dice->rx_pcm_chs[i][mode] > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) !amdtp_stream_running(&dice->rx_stream[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (i < MAX_STREAMS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) // Start both streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) err = snd_dice_transaction_set_enable(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev_err(&dice->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) "fail to enable interface\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) err = amdtp_domain_start(&dice->domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) for (i = 0; i < MAX_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if ((i < tx_params.count &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) !amdtp_stream_wait_callback(&dice->tx_stream[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) CALLBACK_TIMEOUT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) (i < rx_params.count &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) !amdtp_stream_wait_callback(&dice->rx_stream[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) CALLBACK_TIMEOUT))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) amdtp_domain_stop(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) finish_session(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * MEMO: After this function, there're two states of streams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * - None streams are running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * - All streams are running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) void snd_dice_stream_stop_duplex(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct reg_params tx_params, rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (dice->substreams_counter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (get_register_params(dice, &tx_params, &rx_params) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) finish_session(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) amdtp_domain_stop(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) release_resources(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) stream = &dice->tx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) resources = &dice->tx_resources[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) stream = &dice->rx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) resources = &dice->rx_resources[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err = fw_iso_resources_init(resources, dice->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) resources->channels_mask = 0x00000000ffffffffuLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) amdtp_stream_destroy(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) fw_iso_resources_destroy(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * This function should be called before starting streams or after stopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static void destroy_stream(struct snd_dice *dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) enum amdtp_stream_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct amdtp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (dir == AMDTP_IN_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) stream = &dice->tx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) resources = &dice->tx_resources[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) stream = &dice->rx_stream[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) resources = &dice->rx_resources[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) amdtp_stream_destroy(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) fw_iso_resources_destroy(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int snd_dice_stream_init_duplex(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) for (i = 0; i < MAX_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) err = init_stream(dice, AMDTP_IN_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) for (; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) destroy_stream(dice, AMDTP_IN_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) for (i = 0; i < MAX_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) err = init_stream(dice, AMDTP_OUT_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) for (; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) destroy_stream(dice, AMDTP_OUT_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) for (i = 0; i < MAX_STREAMS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) destroy_stream(dice, AMDTP_IN_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) err = amdtp_domain_init(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) for (i = 0; i < MAX_STREAMS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) destroy_stream(dice, AMDTP_OUT_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) destroy_stream(dice, AMDTP_IN_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) for (i = 0; i < MAX_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) destroy_stream(dice, AMDTP_IN_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) destroy_stream(dice, AMDTP_OUT_STREAM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) amdtp_domain_destroy(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) void snd_dice_stream_update_duplex(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct reg_params tx_params, rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * On a bus reset, the DICE firmware disables streaming and then goes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * off contemplating its own navel for hundreds of milliseconds before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * it can react to any of our attempts to reenable streaming. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * means that we lose synchronization anyway, so we force our streams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * to stop so that the application can restart them in an orderly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * manner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) dice->global_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (get_register_params(dice, &tx_params, &rx_params) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) amdtp_domain_stop(&dice->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) enum snd_dice_rate_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) __be32 reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct reg_params tx_params, rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* If extended protocol is available, detect detail spec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) err = snd_dice_detect_extension_formats(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Available stream format is restricted at current mode of sampling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) err = snd_dice_transaction_get_rate(dice, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * Just after owning the unit (GLOBAL_OWNER), the unit can return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * invalid stream formats. Selecting clock parameters have an effect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * for the unit to refine it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) err = ensure_phase_lock(dice, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) err = get_register_params(dice, &tx_params, &rx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) for (i = 0; i < tx_params.count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) err = snd_dice_transaction_read_tx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) tx_params.size * i + TX_NUMBER_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dice->tx_midi_ports[i] = max_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) for (i = 0; i < rx_params.count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) err = snd_dice_transaction_read_rx(dice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) rx_params.size * i + RX_NUMBER_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) reg, sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) dice->rx_midi_ports[i] = max_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static void dice_lock_changed(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) dice->dev_lock_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) wake_up(&dice->hwdep_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int snd_dice_stream_lock_try(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) spin_lock_irq(&dice->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (dice->dev_lock_count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (dice->dev_lock_count++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) dice_lock_changed(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) spin_unlock_irq(&dice->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) void snd_dice_stream_lock_release(struct snd_dice *dice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) spin_lock_irq(&dice->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (WARN_ON(dice->dev_lock_count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (--dice->dev_lock_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) dice_lock_changed(dice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) spin_unlock_irq(&dice->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }