0001
0002
0003
0004
0005
0006
0007
0008 #include "motu.h"
0009
0010 #define READY_TIMEOUT_MS 200
0011
0012 #define ISOC_COMM_CONTROL_OFFSET 0x0b00
0013 #define ISOC_COMM_CONTROL_MASK 0xffff0000
0014 #define CHANGE_RX_ISOC_COMM_STATE 0x80000000
0015 #define RX_ISOC_COMM_IS_ACTIVATED 0x40000000
0016 #define RX_ISOC_COMM_CHANNEL_MASK 0x3f000000
0017 #define RX_ISOC_COMM_CHANNEL_SHIFT 24
0018 #define CHANGE_TX_ISOC_COMM_STATE 0x00800000
0019 #define TX_ISOC_COMM_IS_ACTIVATED 0x00400000
0020 #define TX_ISOC_COMM_CHANNEL_MASK 0x003f0000
0021 #define TX_ISOC_COMM_CHANNEL_SHIFT 16
0022
0023 #define PACKET_FORMAT_OFFSET 0x0b10
0024 #define TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080
0025 #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040
0026 #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f
0027
0028 static int keep_resources(struct snd_motu *motu, unsigned int rate,
0029 struct amdtp_stream *stream)
0030 {
0031 struct fw_iso_resources *resources;
0032 struct snd_motu_packet_format *packet_format;
0033 unsigned int midi_ports = 0;
0034 int err;
0035
0036 if (stream == &motu->rx_stream) {
0037 resources = &motu->rx_resources;
0038 packet_format = &motu->rx_packet_formats;
0039
0040 if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
0041 (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
0042 midi_ports = 1;
0043 } else {
0044 resources = &motu->tx_resources;
0045 packet_format = &motu->tx_packet_formats;
0046
0047 if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
0048 (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
0049 midi_ports = 1;
0050 }
0051
0052 err = amdtp_motu_set_parameters(stream, rate, midi_ports,
0053 packet_format);
0054 if (err < 0)
0055 return err;
0056
0057 return fw_iso_resources_allocate(resources,
0058 amdtp_stream_get_max_payload(stream),
0059 fw_parent_device(motu->unit)->max_speed);
0060 }
0061
0062 static int begin_session(struct snd_motu *motu)
0063 {
0064 __be32 reg;
0065 u32 data;
0066 int err;
0067
0068
0069 err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
0070 sizeof(reg));
0071 if (err < 0)
0072 return err;
0073 data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
0074
0075 data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
0076 (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
0077 CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
0078 (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
0079
0080 reg = cpu_to_be32(data);
0081 return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®,
0082 sizeof(reg));
0083 }
0084
0085 static void finish_session(struct snd_motu *motu)
0086 {
0087 __be32 reg;
0088 u32 data;
0089 int err;
0090
0091 err = snd_motu_protocol_switch_fetching_mode(motu, false);
0092 if (err < 0)
0093 return;
0094
0095 err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
0096 sizeof(reg));
0097 if (err < 0)
0098 return;
0099 data = be32_to_cpu(reg);
0100
0101 data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
0102 data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
0103
0104 reg = cpu_to_be32(data);
0105 snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®,
0106 sizeof(reg));
0107 }
0108
0109 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
0110 {
0111 int err;
0112
0113 err = snd_motu_protocol_cache_packet_formats(motu);
0114 if (err < 0)
0115 return err;
0116
0117 if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
0118 motu->tx_packet_formats.midi_flag_offset = 4;
0119 motu->tx_packet_formats.midi_byte_offset = 6;
0120 } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
0121 motu->tx_packet_formats.midi_flag_offset = 8;
0122 motu->tx_packet_formats.midi_byte_offset = 7;
0123 }
0124
0125 if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
0126 motu->rx_packet_formats.midi_flag_offset = 4;
0127 motu->rx_packet_formats.midi_byte_offset = 6;
0128 } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
0129 motu->rx_packet_formats.midi_flag_offset = 8;
0130 motu->rx_packet_formats.midi_byte_offset = 7;
0131 }
0132
0133 return 0;
0134 }
0135
0136 int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
0137 unsigned int frames_per_period,
0138 unsigned int frames_per_buffer)
0139 {
0140 unsigned int curr_rate;
0141 int err;
0142
0143 err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
0144 if (err < 0)
0145 return err;
0146 if (rate == 0)
0147 rate = curr_rate;
0148
0149 if (motu->substreams_counter == 0 || curr_rate != rate) {
0150 amdtp_domain_stop(&motu->domain);
0151 finish_session(motu);
0152
0153 fw_iso_resources_free(&motu->tx_resources);
0154 fw_iso_resources_free(&motu->rx_resources);
0155
0156 kfree(motu->cache.event_offsets);
0157 motu->cache.event_offsets = NULL;
0158
0159 err = snd_motu_protocol_set_clock_rate(motu, rate);
0160 if (err < 0) {
0161 dev_err(&motu->unit->device,
0162 "fail to set sampling rate: %d\n", err);
0163 return err;
0164 }
0165
0166 err = snd_motu_stream_cache_packet_formats(motu);
0167 if (err < 0)
0168 return err;
0169
0170 err = keep_resources(motu, rate, &motu->tx_stream);
0171 if (err < 0)
0172 return err;
0173
0174 err = keep_resources(motu, rate, &motu->rx_stream);
0175 if (err < 0) {
0176 fw_iso_resources_free(&motu->tx_resources);
0177 return err;
0178 }
0179
0180 err = amdtp_domain_set_events_per_period(&motu->domain,
0181 frames_per_period, frames_per_buffer);
0182 if (err < 0) {
0183 fw_iso_resources_free(&motu->tx_resources);
0184 fw_iso_resources_free(&motu->rx_resources);
0185 return err;
0186 }
0187
0188 motu->cache.size = motu->tx_stream.syt_interval * frames_per_buffer;
0189 motu->cache.event_offsets = kcalloc(motu->cache.size, sizeof(*motu->cache.event_offsets),
0190 GFP_KERNEL);
0191 if (!motu->cache.event_offsets) {
0192 fw_iso_resources_free(&motu->tx_resources);
0193 fw_iso_resources_free(&motu->rx_resources);
0194 return -ENOMEM;
0195 }
0196 }
0197
0198 return 0;
0199 }
0200
0201 static int ensure_packet_formats(struct snd_motu *motu)
0202 {
0203 __be32 reg;
0204 u32 data;
0205 int err;
0206
0207 err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, ®,
0208 sizeof(reg));
0209 if (err < 0)
0210 return err;
0211 data = be32_to_cpu(reg);
0212
0213 data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
0214 RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
0215 TX_PACKET_TRANSMISSION_SPEED_MASK);
0216 if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
0217 data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
0218 if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
0219 data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
0220 data |= fw_parent_device(motu->unit)->max_speed;
0221
0222 reg = cpu_to_be32(data);
0223 return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, ®,
0224 sizeof(reg));
0225 }
0226
0227 int snd_motu_stream_start_duplex(struct snd_motu *motu)
0228 {
0229 unsigned int generation = motu->rx_resources.generation;
0230 int err = 0;
0231
0232 if (motu->substreams_counter == 0)
0233 return 0;
0234
0235 if (amdtp_streaming_error(&motu->rx_stream) ||
0236 amdtp_streaming_error(&motu->tx_stream)) {
0237 amdtp_domain_stop(&motu->domain);
0238 finish_session(motu);
0239 }
0240
0241 if (generation != fw_parent_device(motu->unit)->card->generation) {
0242 err = fw_iso_resources_update(&motu->rx_resources);
0243 if (err < 0)
0244 return err;
0245
0246 err = fw_iso_resources_update(&motu->tx_resources);
0247 if (err < 0)
0248 return err;
0249 }
0250
0251 if (!amdtp_stream_running(&motu->rx_stream)) {
0252 int spd = fw_parent_device(motu->unit)->max_speed;
0253
0254 err = ensure_packet_formats(motu);
0255 if (err < 0)
0256 return err;
0257
0258 if (motu->spec->flags & SND_MOTU_SPEC_REGISTER_DSP) {
0259 err = snd_motu_register_dsp_message_parser_init(motu);
0260 if (err < 0)
0261 return err;
0262 } else if (motu->spec->flags & SND_MOTU_SPEC_COMMAND_DSP) {
0263 err = snd_motu_command_dsp_message_parser_init(motu, motu->tx_stream.sfc);
0264 if (err < 0)
0265 return err;
0266 }
0267
0268 err = begin_session(motu);
0269 if (err < 0) {
0270 dev_err(&motu->unit->device,
0271 "fail to start isochronous comm: %d\n", err);
0272 goto stop_streams;
0273 }
0274
0275 err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
0276 motu->tx_resources.channel, spd);
0277 if (err < 0)
0278 goto stop_streams;
0279
0280 err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream,
0281 motu->rx_resources.channel, spd);
0282 if (err < 0)
0283 goto stop_streams;
0284
0285 motu->cache.tail = 0;
0286 motu->cache.tx_cycle_count = UINT_MAX;
0287 motu->cache.head = 0;
0288 motu->cache.rx_cycle_count = UINT_MAX;
0289
0290
0291
0292
0293 err = amdtp_domain_start(&motu->domain, 0, true, false);
0294 if (err < 0)
0295 goto stop_streams;
0296
0297 if (!amdtp_domain_wait_ready(&motu->domain, READY_TIMEOUT_MS)) {
0298 err = -ETIMEDOUT;
0299 goto stop_streams;
0300 }
0301
0302 err = snd_motu_protocol_switch_fetching_mode(motu, true);
0303 if (err < 0) {
0304 dev_err(&motu->unit->device,
0305 "fail to enable frame fetching: %d\n", err);
0306 goto stop_streams;
0307 }
0308 }
0309
0310 return 0;
0311
0312 stop_streams:
0313 amdtp_domain_stop(&motu->domain);
0314 finish_session(motu);
0315 return err;
0316 }
0317
0318 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
0319 {
0320 if (motu->substreams_counter == 0) {
0321 amdtp_domain_stop(&motu->domain);
0322 finish_session(motu);
0323
0324 fw_iso_resources_free(&motu->tx_resources);
0325 fw_iso_resources_free(&motu->rx_resources);
0326
0327 kfree(motu->cache.event_offsets);
0328 motu->cache.event_offsets = NULL;
0329 }
0330 }
0331
0332 static int init_stream(struct snd_motu *motu, struct amdtp_stream *s)
0333 {
0334 struct fw_iso_resources *resources;
0335 enum amdtp_stream_direction dir;
0336 int err;
0337
0338 if (s == &motu->tx_stream) {
0339 resources = &motu->tx_resources;
0340 dir = AMDTP_IN_STREAM;
0341 } else {
0342 resources = &motu->rx_resources;
0343 dir = AMDTP_OUT_STREAM;
0344 }
0345
0346 err = fw_iso_resources_init(resources, motu->unit);
0347 if (err < 0)
0348 return err;
0349
0350 err = amdtp_motu_init(s, motu->unit, dir, motu->spec, &motu->cache);
0351 if (err < 0)
0352 fw_iso_resources_destroy(resources);
0353
0354 return err;
0355 }
0356
0357 static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s)
0358 {
0359 amdtp_stream_destroy(s);
0360
0361 if (s == &motu->tx_stream)
0362 fw_iso_resources_destroy(&motu->tx_resources);
0363 else
0364 fw_iso_resources_destroy(&motu->rx_resources);
0365 }
0366
0367 int snd_motu_stream_init_duplex(struct snd_motu *motu)
0368 {
0369 int err;
0370
0371 err = init_stream(motu, &motu->tx_stream);
0372 if (err < 0)
0373 return err;
0374
0375 err = init_stream(motu, &motu->rx_stream);
0376 if (err < 0) {
0377 destroy_stream(motu, &motu->tx_stream);
0378 return err;
0379 }
0380
0381 err = amdtp_domain_init(&motu->domain);
0382 if (err < 0) {
0383 destroy_stream(motu, &motu->tx_stream);
0384 destroy_stream(motu, &motu->rx_stream);
0385 }
0386
0387 return err;
0388 }
0389
0390
0391
0392 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
0393 {
0394 amdtp_domain_destroy(&motu->domain);
0395
0396 destroy_stream(motu, &motu->rx_stream);
0397 destroy_stream(motu, &motu->tx_stream);
0398
0399 motu->substreams_counter = 0;
0400 }
0401
0402 static void motu_lock_changed(struct snd_motu *motu)
0403 {
0404 motu->dev_lock_changed = true;
0405 wake_up(&motu->hwdep_wait);
0406 }
0407
0408 int snd_motu_stream_lock_try(struct snd_motu *motu)
0409 {
0410 int err;
0411
0412 spin_lock_irq(&motu->lock);
0413
0414 if (motu->dev_lock_count < 0) {
0415 err = -EBUSY;
0416 goto out;
0417 }
0418
0419 if (motu->dev_lock_count++ == 0)
0420 motu_lock_changed(motu);
0421 err = 0;
0422 out:
0423 spin_unlock_irq(&motu->lock);
0424 return err;
0425 }
0426
0427 void snd_motu_stream_lock_release(struct snd_motu *motu)
0428 {
0429 spin_lock_irq(&motu->lock);
0430
0431 if (WARN_ON(motu->dev_lock_count <= 0))
0432 goto out;
0433
0434 if (--motu->dev_lock_count == 0)
0435 motu_lock_changed(motu);
0436 out:
0437 spin_unlock_irq(&motu->lock);
0438 }