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 keep_resources(struct snd_motu *motu, unsigned int rate, 30 struct amdtp_stream *stream) 31 { 32 struct fw_iso_resources *resources; 33 struct snd_motu_packet_format *packet_format; 34 unsigned int midi_ports = 0; 35 int err; 36 37 if (stream == &motu->rx_stream) { 38 resources = &motu->rx_resources; 39 packet_format = &motu->rx_packet_formats; 40 41 if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) || 42 (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q)) 43 midi_ports = 1; 44 } else { 45 resources = &motu->tx_resources; 46 packet_format = &motu->tx_packet_formats; 47 48 if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) || 49 (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q)) 50 midi_ports = 1; 51 } 52 53 err = amdtp_motu_set_parameters(stream, rate, midi_ports, 54 packet_format); 55 if (err < 0) 56 return err; 57 58 return fw_iso_resources_allocate(resources, 59 amdtp_stream_get_max_payload(stream), 60 fw_parent_device(motu->unit)->max_speed); 61 } 62 63 static int begin_session(struct snd_motu *motu) 64 { 65 __be32 reg; 66 u32 data; 67 int 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 finish_session(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 amdtp_stream_stop(&motu->tx_stream); 97 amdtp_stream_stop(&motu->rx_stream); 98 99 err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, 100 sizeof(reg)); 101 if (err < 0) 102 return; 103 data = be32_to_cpu(reg); 104 105 data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED); 106 data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE; 107 108 reg = cpu_to_be32(data); 109 snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®, 110 sizeof(reg)); 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 return -ETIMEDOUT; 130 131 return 0; 132 } 133 134 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) 135 { 136 int err; 137 138 err = motu->spec->protocol->cache_packet_formats(motu); 139 if (err < 0) 140 return err; 141 142 if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) { 143 motu->tx_packet_formats.midi_flag_offset = 4; 144 motu->tx_packet_formats.midi_byte_offset = 6; 145 } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) { 146 motu->tx_packet_formats.midi_flag_offset = 8; 147 motu->tx_packet_formats.midi_byte_offset = 7; 148 } 149 150 if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) { 151 motu->rx_packet_formats.midi_flag_offset = 4; 152 motu->rx_packet_formats.midi_byte_offset = 6; 153 } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) { 154 motu->rx_packet_formats.midi_flag_offset = 8; 155 motu->rx_packet_formats.midi_byte_offset = 7; 156 } 157 158 return 0; 159 } 160 161 int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate) 162 { 163 unsigned int curr_rate; 164 int err; 165 166 err = motu->spec->protocol->get_clock_rate(motu, &curr_rate); 167 if (err < 0) 168 return err; 169 if (rate == 0) 170 rate = curr_rate; 171 172 if (motu->substreams_counter == 0 || curr_rate != rate) { 173 finish_session(motu); 174 175 fw_iso_resources_free(&motu->tx_resources); 176 fw_iso_resources_free(&motu->rx_resources); 177 178 err = motu->spec->protocol->set_clock_rate(motu, rate); 179 if (err < 0) { 180 dev_err(&motu->unit->device, 181 "fail to set sampling rate: %d\n", err); 182 return err; 183 } 184 185 err = snd_motu_stream_cache_packet_formats(motu); 186 if (err < 0) 187 return err; 188 189 err = keep_resources(motu, rate, &motu->tx_stream); 190 if (err < 0) 191 return err; 192 193 err = keep_resources(motu, rate, &motu->rx_stream); 194 if (err < 0) { 195 fw_iso_resources_free(&motu->tx_resources); 196 return err; 197 } 198 } 199 200 return 0; 201 } 202 203 static int ensure_packet_formats(struct snd_motu *motu) 204 { 205 __be32 reg; 206 u32 data; 207 int err; 208 209 err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, ®, 210 sizeof(reg)); 211 if (err < 0) 212 return err; 213 data = be32_to_cpu(reg); 214 215 data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS | 216 RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS| 217 TX_PACKET_TRANSMISSION_SPEED_MASK); 218 if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0) 219 data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; 220 if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0) 221 data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; 222 data |= fw_parent_device(motu->unit)->max_speed; 223 224 reg = cpu_to_be32(data); 225 return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, ®, 226 sizeof(reg)); 227 } 228 229 int snd_motu_stream_start_duplex(struct snd_motu *motu) 230 { 231 unsigned int generation = motu->rx_resources.generation; 232 int err = 0; 233 234 if (motu->substreams_counter == 0) 235 return 0; 236 237 if (amdtp_streaming_error(&motu->rx_stream) || 238 amdtp_streaming_error(&motu->tx_stream)) 239 finish_session(motu); 240 241 if (generation != fw_parent_device(motu->unit)->card->generation) { 242 err = fw_iso_resources_update(&motu->rx_resources); 243 if (err < 0) 244 return err; 245 246 err = fw_iso_resources_update(&motu->tx_resources); 247 if (err < 0) 248 return err; 249 } 250 251 if (!amdtp_stream_running(&motu->rx_stream)) { 252 err = ensure_packet_formats(motu); 253 if (err < 0) 254 return err; 255 256 err = begin_session(motu); 257 if (err < 0) { 258 dev_err(&motu->unit->device, 259 "fail to start isochronous comm: %d\n", err); 260 goto stop_streams; 261 } 262 263 err = start_isoc_ctx(motu, &motu->rx_stream); 264 if (err < 0) { 265 dev_err(&motu->unit->device, 266 "fail to start IT context: %d\n", err); 267 goto stop_streams; 268 } 269 270 err = motu->spec->protocol->switch_fetching_mode(motu, true); 271 if (err < 0) { 272 dev_err(&motu->unit->device, 273 "fail to enable frame fetching: %d\n", err); 274 goto stop_streams; 275 } 276 } 277 278 if (!amdtp_stream_running(&motu->tx_stream)) { 279 err = start_isoc_ctx(motu, &motu->tx_stream); 280 if (err < 0) { 281 dev_err(&motu->unit->device, 282 "fail to start IR context: %d", err); 283 goto stop_streams; 284 } 285 } 286 287 return 0; 288 289 stop_streams: 290 finish_session(motu); 291 return err; 292 } 293 294 void snd_motu_stream_stop_duplex(struct snd_motu *motu) 295 { 296 if (motu->substreams_counter == 0) { 297 finish_session(motu); 298 299 fw_iso_resources_free(&motu->tx_resources); 300 fw_iso_resources_free(&motu->rx_resources); 301 } 302 } 303 304 static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) 305 { 306 int err; 307 struct amdtp_stream *stream; 308 struct fw_iso_resources *resources; 309 310 if (dir == AMDTP_IN_STREAM) { 311 stream = &motu->tx_stream; 312 resources = &motu->tx_resources; 313 } else { 314 stream = &motu->rx_stream; 315 resources = &motu->rx_resources; 316 } 317 318 err = fw_iso_resources_init(resources, motu->unit); 319 if (err < 0) 320 return err; 321 322 err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol); 323 if (err < 0) { 324 amdtp_stream_destroy(stream); 325 fw_iso_resources_destroy(resources); 326 } 327 328 return err; 329 } 330 331 static void destroy_stream(struct snd_motu *motu, 332 enum amdtp_stream_direction dir) 333 { 334 struct amdtp_stream *stream; 335 struct fw_iso_resources *resources; 336 337 if (dir == AMDTP_IN_STREAM) { 338 stream = &motu->tx_stream; 339 resources = &motu->tx_resources; 340 } else { 341 stream = &motu->rx_stream; 342 resources = &motu->rx_resources; 343 } 344 345 amdtp_stream_destroy(stream); 346 fw_iso_resources_free(resources); 347 } 348 349 int snd_motu_stream_init_duplex(struct snd_motu *motu) 350 { 351 int err; 352 353 err = init_stream(motu, AMDTP_IN_STREAM); 354 if (err < 0) 355 return err; 356 357 err = init_stream(motu, AMDTP_OUT_STREAM); 358 if (err < 0) 359 destroy_stream(motu, AMDTP_IN_STREAM); 360 361 return err; 362 } 363 364 /* 365 * This function should be called before starting streams or after stopping 366 * streams. 367 */ 368 void snd_motu_stream_destroy_duplex(struct snd_motu *motu) 369 { 370 destroy_stream(motu, AMDTP_IN_STREAM); 371 destroy_stream(motu, AMDTP_OUT_STREAM); 372 373 motu->substreams_counter = 0; 374 } 375 376 static void motu_lock_changed(struct snd_motu *motu) 377 { 378 motu->dev_lock_changed = true; 379 wake_up(&motu->hwdep_wait); 380 } 381 382 int snd_motu_stream_lock_try(struct snd_motu *motu) 383 { 384 int err; 385 386 spin_lock_irq(&motu->lock); 387 388 if (motu->dev_lock_count < 0) { 389 err = -EBUSY; 390 goto out; 391 } 392 393 if (motu->dev_lock_count++ == 0) 394 motu_lock_changed(motu); 395 err = 0; 396 out: 397 spin_unlock_irq(&motu->lock); 398 return err; 399 } 400 401 void snd_motu_stream_lock_release(struct snd_motu *motu) 402 { 403 spin_lock_irq(&motu->lock); 404 405 if (WARN_ON(motu->dev_lock_count <= 0)) 406 goto out; 407 408 if (--motu->dev_lock_count == 0) 409 motu_lock_changed(motu); 410 out: 411 spin_unlock_irq(&motu->lock); 412 } 413