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