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