^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) * motu-stream.c - a part of driver for MOTU FireWire series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
^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 "motu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define CALLBACK_TIMEOUT 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define ISOC_COMM_CONTROL_OFFSET 0x0b00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define ISOC_COMM_CONTROL_MASK 0xffff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CHANGE_RX_ISOC_COMM_STATE 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define RX_ISOC_COMM_IS_ACTIVATED 0x40000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define RX_ISOC_COMM_CHANNEL_MASK 0x3f000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define RX_ISOC_COMM_CHANNEL_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define CHANGE_TX_ISOC_COMM_STATE 0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define TX_ISOC_COMM_IS_ACTIVATED 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define TX_ISOC_COMM_CHANNEL_MASK 0x003f0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define TX_ISOC_COMM_CHANNEL_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PACKET_FORMAT_OFFSET 0x0b10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int keep_resources(struct snd_motu *motu, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct snd_motu_packet_format *packet_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned int midi_ports = 0;
^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) if (stream == &motu->rx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) resources = &motu->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) packet_format = &motu->rx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) midi_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) resources = &motu->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) packet_format = &motu->tx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) midi_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) err = amdtp_motu_set_parameters(stream, rate, midi_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) packet_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return fw_iso_resources_allocate(resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) amdtp_stream_get_max_payload(stream),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) fw_parent_device(motu->unit)->max_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int begin_session(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) // Configure the unit to start isochronous communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void finish_session(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) err = snd_motu_protocol_switch_fetching_mode(motu, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) err = snd_motu_protocol_cache_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) motu->tx_packet_formats.midi_flag_offset = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) motu->tx_packet_formats.midi_byte_offset = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) motu->tx_packet_formats.midi_flag_offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) motu->tx_packet_formats.midi_byte_offset = 7;
^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) if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) motu->rx_packet_formats.midi_flag_offset = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) motu->rx_packet_formats.midi_byte_offset = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) motu->rx_packet_formats.midi_flag_offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) motu->rx_packet_formats.midi_byte_offset = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned int frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int frames_per_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rate = curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (motu->substreams_counter == 0 || curr_rate != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) err = snd_motu_protocol_set_clock_rate(motu, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) "fail to set sampling rate: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) err = snd_motu_stream_cache_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) err = keep_resources(motu, rate, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) err = keep_resources(motu, rate, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fw_iso_resources_free(&motu->tx_resources);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err = amdtp_domain_set_events_per_period(&motu->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return err;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int ensure_packet_formats(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) __be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u32 data;
^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) err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) TX_PACKET_TRANSMISSION_SPEED_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) data |= fw_parent_device(motu->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, ®,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int snd_motu_stream_start_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned int generation = motu->rx_resources.generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (motu->substreams_counter == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (amdtp_streaming_error(&motu->rx_stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) amdtp_streaming_error(&motu->tx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (generation != fw_parent_device(motu->unit)->card->generation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) err = fw_iso_resources_update(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) err = fw_iso_resources_update(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!amdtp_stream_running(&motu->rx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int spd = fw_parent_device(motu->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) err = ensure_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) err = begin_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) "fail to start isochronous comm: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) goto stop_streams;
^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) err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) motu->tx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) motu->rx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) err = amdtp_domain_start(&motu->domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!amdtp_stream_wait_callback(&motu->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) CALLBACK_TIMEOUT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) !amdtp_stream_wait_callback(&motu->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) CALLBACK_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto stop_streams;
^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) err = snd_motu_protocol_switch_fetching_mode(motu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "fail to enable frame fetching: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) stop_streams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) void snd_motu_stream_stop_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (motu->substreams_counter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int init_stream(struct snd_motu *motu, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) enum amdtp_stream_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (s == &motu->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) resources = &motu->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dir = AMDTP_IN_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) resources = &motu->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dir = AMDTP_OUT_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err = fw_iso_resources_init(resources, motu->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (err < 0)
^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) err = amdtp_motu_init(s, motu->unit, dir, motu->spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) fw_iso_resources_destroy(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) amdtp_stream_destroy(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (s == &motu->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) fw_iso_resources_destroy(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) fw_iso_resources_destroy(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int snd_motu_stream_init_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) err = init_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) err = init_stream(motu, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return err;
^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) err = amdtp_domain_init(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) destroy_stream(motu, &motu->rx_stream);
^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) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) // This function should be called before starting streams or after stopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) // streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) amdtp_domain_destroy(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) destroy_stream(motu, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) motu->substreams_counter = 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 void motu_lock_changed(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) motu->dev_lock_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) wake_up(&motu->hwdep_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int snd_motu_stream_lock_try(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) spin_lock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (motu->dev_lock_count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (motu->dev_lock_count++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) motu_lock_changed(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) spin_unlock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) void snd_motu_stream_lock_release(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) spin_lock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (WARN_ON(motu->dev_lock_count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (--motu->dev_lock_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) motu_lock_changed(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) spin_unlock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }