1 /* 2 * tascam-stream.c - a part of driver for TASCAM FireWire series 3 * 4 * Copyright (c) 2015 Takashi Sakamoto 5 * 6 * Licensed under the terms of the GNU General Public License, version 2. 7 */ 8 9 #include <linux/delay.h> 10 #include "tascam.h" 11 12 #define CALLBACK_TIMEOUT 500 13 14 static int get_clock(struct snd_tscm *tscm, u32 *data) 15 { 16 __be32 reg; 17 int err; 18 19 err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST, 20 TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS, 21 ®, sizeof(reg), 0); 22 if (err >= 0) 23 *data = be32_to_cpu(reg); 24 25 return err; 26 } 27 28 static int set_clock(struct snd_tscm *tscm, unsigned int rate, 29 enum snd_tscm_clock clock) 30 { 31 u32 data; 32 __be32 reg; 33 int err; 34 35 err = get_clock(tscm, &data); 36 if (err < 0) 37 return err; 38 data &= 0x0000ffff; 39 40 if (rate > 0) { 41 data &= 0x000000ff; 42 /* Base rate. */ 43 if ((rate % 44100) == 0) { 44 data |= 0x00000100; 45 /* Multiplier. */ 46 if (rate / 44100 == 2) 47 data |= 0x00008000; 48 } else if ((rate % 48000) == 0) { 49 data |= 0x00000200; 50 /* Multiplier. */ 51 if (rate / 48000 == 2) 52 data |= 0x00008000; 53 } else { 54 return -EAGAIN; 55 } 56 } 57 58 if (clock != INT_MAX) { 59 data &= 0x0000ff00; 60 data |= clock + 1; 61 } 62 63 reg = cpu_to_be32(data); 64 65 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 66 TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS, 67 ®, sizeof(reg), 0); 68 if (err < 0) 69 return err; 70 71 if (data & 0x00008000) 72 reg = cpu_to_be32(0x0000001a); 73 else 74 reg = cpu_to_be32(0x0000000d); 75 76 return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 77 TSCM_ADDR_BASE + TSCM_OFFSET_MULTIPLEX_MODE, 78 ®, sizeof(reg), 0); 79 } 80 81 int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate) 82 { 83 u32 data = 0x0; 84 unsigned int trials = 0; 85 int err; 86 87 while (data == 0x0 || trials++ < 5) { 88 err = get_clock(tscm, &data); 89 if (err < 0) 90 return err; 91 92 data = (data & 0xff000000) >> 24; 93 } 94 95 /* Check base rate. */ 96 if ((data & 0x0f) == 0x01) 97 *rate = 44100; 98 else if ((data & 0x0f) == 0x02) 99 *rate = 48000; 100 else 101 return -EAGAIN; 102 103 /* Check multiplier. */ 104 if ((data & 0xf0) == 0x80) 105 *rate *= 2; 106 else if ((data & 0xf0) != 0x00) 107 return -EAGAIN; 108 109 return err; 110 } 111 112 int snd_tscm_stream_get_clock(struct snd_tscm *tscm, enum snd_tscm_clock *clock) 113 { 114 u32 data; 115 int err; 116 117 err = get_clock(tscm, &data); 118 if (err < 0) 119 return err; 120 121 *clock = ((data & 0x00ff0000) >> 16) - 1; 122 if (*clock < 0 || *clock > SND_TSCM_CLOCK_ADAT) 123 return -EIO; 124 125 return 0; 126 } 127 128 static int enable_data_channels(struct snd_tscm *tscm) 129 { 130 __be32 reg; 131 u32 data; 132 unsigned int i; 133 int err; 134 135 data = 0; 136 for (i = 0; i < tscm->spec->pcm_capture_analog_channels; ++i) 137 data |= BIT(i); 138 if (tscm->spec->has_adat) 139 data |= 0x0000ff00; 140 if (tscm->spec->has_spdif) 141 data |= 0x00030000; 142 143 reg = cpu_to_be32(data); 144 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 145 TSCM_ADDR_BASE + TSCM_OFFSET_TX_PCM_CHANNELS, 146 ®, sizeof(reg), 0); 147 if (err < 0) 148 return err; 149 150 data = 0; 151 for (i = 0; i < tscm->spec->pcm_playback_analog_channels; ++i) 152 data |= BIT(i); 153 if (tscm->spec->has_adat) 154 data |= 0x0000ff00; 155 if (tscm->spec->has_spdif) 156 data |= 0x00030000; 157 158 reg = cpu_to_be32(data); 159 return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 160 TSCM_ADDR_BASE + TSCM_OFFSET_RX_PCM_CHANNELS, 161 ®, sizeof(reg), 0); 162 } 163 164 static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate) 165 { 166 __be32 reg; 167 int err; 168 169 // Set an option for unknown purpose. 170 reg = cpu_to_be32(0x00200000); 171 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 172 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION, 173 ®, sizeof(reg), 0); 174 if (err < 0) 175 return err; 176 177 return enable_data_channels(tscm); 178 } 179 180 static void finish_session(struct snd_tscm *tscm) 181 { 182 __be32 reg; 183 184 amdtp_stream_stop(&tscm->rx_stream); 185 amdtp_stream_stop(&tscm->tx_stream); 186 187 reg = 0; 188 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 189 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, 190 ®, sizeof(reg), 0); 191 192 reg = 0; 193 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 194 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON, 195 ®, sizeof(reg), 0); 196 197 // Unregister channels. 198 reg = cpu_to_be32(0x00000000); 199 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 200 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, 201 ®, sizeof(reg), 0); 202 reg = cpu_to_be32(0x00000000); 203 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 204 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, 205 ®, sizeof(reg), 0); 206 reg = cpu_to_be32(0x00000000); 207 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 208 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, 209 ®, sizeof(reg), 0); 210 } 211 212 static int begin_session(struct snd_tscm *tscm) 213 { 214 __be32 reg; 215 int err; 216 217 // Register the isochronous channel for transmitting stream. 218 reg = cpu_to_be32(tscm->tx_resources.channel); 219 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 220 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, 221 ®, sizeof(reg), 0); 222 if (err < 0) 223 return err; 224 225 // Unknown. 226 reg = cpu_to_be32(0x00000002); 227 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 228 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, 229 ®, sizeof(reg), 0); 230 if (err < 0) 231 return err; 232 233 // Register the isochronous channel for receiving stream. 234 reg = cpu_to_be32(tscm->rx_resources.channel); 235 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 236 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, 237 ®, sizeof(reg), 0); 238 if (err < 0) 239 return err; 240 241 reg = cpu_to_be32(0x00000001); 242 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 243 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, 244 ®, sizeof(reg), 0); 245 if (err < 0) 246 return err; 247 248 reg = cpu_to_be32(0x00000001); 249 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 250 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON, 251 ®, sizeof(reg), 0); 252 if (err < 0) 253 return err; 254 255 // Set an option for unknown purpose. 256 reg = cpu_to_be32(0x00002000); 257 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 258 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION, 259 ®, sizeof(reg), 0); 260 if (err < 0) 261 return err; 262 263 // Start multiplexing PCM samples on packets. 264 reg = cpu_to_be32(0x00000001); 265 return snd_fw_transaction(tscm->unit, 266 TCODE_WRITE_QUADLET_REQUEST, 267 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON, 268 ®, sizeof(reg), 0); 269 } 270 271 static int keep_resources(struct snd_tscm *tscm, unsigned int rate, 272 struct amdtp_stream *stream) 273 { 274 struct fw_iso_resources *resources; 275 int err; 276 277 if (stream == &tscm->tx_stream) 278 resources = &tscm->tx_resources; 279 else 280 resources = &tscm->rx_resources; 281 282 err = amdtp_tscm_set_parameters(stream, rate); 283 if (err < 0) 284 return err; 285 286 return fw_iso_resources_allocate(resources, 287 amdtp_stream_get_max_payload(stream), 288 fw_parent_device(tscm->unit)->max_speed); 289 } 290 291 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) 292 { 293 unsigned int pcm_channels; 294 int err; 295 296 /* For out-stream. */ 297 err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit); 298 if (err < 0) 299 return err; 300 pcm_channels = tscm->spec->pcm_playback_analog_channels; 301 if (tscm->spec->has_adat) 302 pcm_channels += 8; 303 if (tscm->spec->has_spdif) 304 pcm_channels += 2; 305 err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM, 306 pcm_channels); 307 if (err < 0) 308 return err; 309 310 /* For in-stream. */ 311 err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit); 312 if (err < 0) 313 return err; 314 pcm_channels = tscm->spec->pcm_capture_analog_channels; 315 if (tscm->spec->has_adat) 316 pcm_channels += 8; 317 if (tscm->spec->has_spdif) 318 pcm_channels += 2; 319 err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM, 320 pcm_channels); 321 if (err < 0) 322 amdtp_stream_destroy(&tscm->rx_stream); 323 324 return err; 325 } 326 327 // At bus reset, streaming is stopped and some registers are clear. 328 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) 329 { 330 amdtp_stream_pcm_abort(&tscm->tx_stream); 331 amdtp_stream_stop(&tscm->tx_stream); 332 333 amdtp_stream_pcm_abort(&tscm->rx_stream); 334 amdtp_stream_stop(&tscm->rx_stream); 335 } 336 337 /* 338 * This function should be called before starting streams or after stopping 339 * streams. 340 */ 341 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) 342 { 343 amdtp_stream_destroy(&tscm->rx_stream); 344 amdtp_stream_destroy(&tscm->tx_stream); 345 346 fw_iso_resources_destroy(&tscm->rx_resources); 347 fw_iso_resources_destroy(&tscm->tx_resources); 348 } 349 350 int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) 351 { 352 unsigned int curr_rate; 353 int err; 354 355 err = snd_tscm_stream_get_rate(tscm, &curr_rate); 356 if (err < 0) 357 return err; 358 359 if (tscm->substreams_counter == 0 || rate != curr_rate) { 360 finish_session(tscm); 361 362 fw_iso_resources_free(&tscm->tx_resources); 363 fw_iso_resources_free(&tscm->rx_resources); 364 365 err = set_clock(tscm, rate, INT_MAX); 366 if (err < 0) 367 return err; 368 369 err = keep_resources(tscm, rate, &tscm->tx_stream); 370 if (err < 0) 371 return err; 372 373 err = keep_resources(tscm, rate, &tscm->rx_stream); 374 if (err < 0) { 375 fw_iso_resources_free(&tscm->tx_resources); 376 return err; 377 } 378 } 379 380 return 0; 381 } 382 383 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) 384 { 385 unsigned int generation = tscm->rx_resources.generation; 386 int err; 387 388 if (tscm->substreams_counter == 0) 389 return 0; 390 391 if (amdtp_streaming_error(&tscm->rx_stream) || 392 amdtp_streaming_error(&tscm->tx_stream)) 393 finish_session(tscm); 394 395 if (generation != fw_parent_device(tscm->unit)->card->generation) { 396 err = fw_iso_resources_update(&tscm->tx_resources); 397 if (err < 0) 398 goto error; 399 400 err = fw_iso_resources_update(&tscm->rx_resources); 401 if (err < 0) 402 goto error; 403 } 404 405 if (!amdtp_stream_running(&tscm->rx_stream)) { 406 err = set_stream_formats(tscm, rate); 407 if (err < 0) 408 goto error; 409 410 err = begin_session(tscm); 411 if (err < 0) 412 goto error; 413 414 err = amdtp_stream_start(&tscm->rx_stream, 415 tscm->rx_resources.channel, 416 fw_parent_device(tscm->unit)->max_speed); 417 if (err < 0) 418 goto error; 419 420 if (!amdtp_stream_wait_callback(&tscm->rx_stream, 421 CALLBACK_TIMEOUT)) { 422 err = -ETIMEDOUT; 423 goto error; 424 } 425 } 426 427 if (!amdtp_stream_running(&tscm->tx_stream)) { 428 err = amdtp_stream_start(&tscm->tx_stream, 429 tscm->tx_resources.channel, 430 fw_parent_device(tscm->unit)->max_speed); 431 if (err < 0) 432 goto error; 433 434 if (!amdtp_stream_wait_callback(&tscm->tx_stream, 435 CALLBACK_TIMEOUT)) { 436 err = -ETIMEDOUT; 437 goto error; 438 } 439 } 440 441 return 0; 442 error: 443 finish_session(tscm); 444 445 return err; 446 } 447 448 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) 449 { 450 if (tscm->substreams_counter == 0) { 451 finish_session(tscm); 452 453 fw_iso_resources_free(&tscm->tx_resources); 454 fw_iso_resources_free(&tscm->rx_resources); 455 } 456 } 457 458 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) 459 { 460 tscm->dev_lock_changed = true; 461 wake_up(&tscm->hwdep_wait); 462 } 463 464 int snd_tscm_stream_lock_try(struct snd_tscm *tscm) 465 { 466 int err; 467 468 spin_lock_irq(&tscm->lock); 469 470 /* user land lock this */ 471 if (tscm->dev_lock_count < 0) { 472 err = -EBUSY; 473 goto end; 474 } 475 476 /* this is the first time */ 477 if (tscm->dev_lock_count++ == 0) 478 snd_tscm_stream_lock_changed(tscm); 479 err = 0; 480 end: 481 spin_unlock_irq(&tscm->lock); 482 return err; 483 } 484 485 void snd_tscm_stream_lock_release(struct snd_tscm *tscm) 486 { 487 spin_lock_irq(&tscm->lock); 488 489 if (WARN_ON(tscm->dev_lock_count <= 0)) 490 goto end; 491 if (--tscm->dev_lock_count == 0) 492 snd_tscm_stream_lock_changed(tscm); 493 end: 494 spin_unlock_irq(&tscm->lock); 495 } 496