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 err = enable_data_channels(tscm); 178 if (err < 0) 179 return err; 180 181 return set_clock(tscm, rate, INT_MAX); 182 } 183 184 static void finish_session(struct snd_tscm *tscm) 185 { 186 __be32 reg; 187 188 reg = 0; 189 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 190 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, 191 ®, sizeof(reg), 0); 192 193 reg = 0; 194 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 195 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON, 196 ®, sizeof(reg), 0); 197 198 } 199 200 static int begin_session(struct snd_tscm *tscm) 201 { 202 __be32 reg; 203 int err; 204 205 reg = cpu_to_be32(0x00000001); 206 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 207 TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, 208 ®, sizeof(reg), 0); 209 if (err < 0) 210 return err; 211 212 reg = cpu_to_be32(0x00000001); 213 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 214 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON, 215 ®, sizeof(reg), 0); 216 if (err < 0) 217 return err; 218 219 /* Set an option for unknown purpose. */ 220 reg = cpu_to_be32(0x00002000); 221 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 222 TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION, 223 ®, sizeof(reg), 0); 224 if (err < 0) 225 return err; 226 227 /* Start multiplexing PCM samples on packets. */ 228 reg = cpu_to_be32(0x00000001); 229 return snd_fw_transaction(tscm->unit, 230 TCODE_WRITE_QUADLET_REQUEST, 231 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON, 232 ®, sizeof(reg), 0); 233 } 234 235 static void release_resources(struct snd_tscm *tscm) 236 { 237 __be32 reg; 238 239 /* Unregister channels. */ 240 reg = cpu_to_be32(0x00000000); 241 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 242 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, 243 ®, sizeof(reg), 0); 244 reg = cpu_to_be32(0x00000000); 245 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 246 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, 247 ®, sizeof(reg), 0); 248 reg = cpu_to_be32(0x00000000); 249 snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 250 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, 251 ®, sizeof(reg), 0); 252 253 /* Release isochronous resources. */ 254 fw_iso_resources_free(&tscm->tx_resources); 255 fw_iso_resources_free(&tscm->rx_resources); 256 } 257 258 static int keep_resources(struct snd_tscm *tscm, unsigned int rate) 259 { 260 __be32 reg; 261 int err; 262 263 /* Keep resources for in-stream. */ 264 err = amdtp_tscm_set_parameters(&tscm->tx_stream, rate); 265 if (err < 0) 266 return err; 267 err = fw_iso_resources_allocate(&tscm->tx_resources, 268 amdtp_stream_get_max_payload(&tscm->tx_stream), 269 fw_parent_device(tscm->unit)->max_speed); 270 if (err < 0) 271 goto error; 272 273 /* Keep resources for out-stream. */ 274 err = amdtp_tscm_set_parameters(&tscm->rx_stream, rate); 275 if (err < 0) 276 return err; 277 err = fw_iso_resources_allocate(&tscm->rx_resources, 278 amdtp_stream_get_max_payload(&tscm->rx_stream), 279 fw_parent_device(tscm->unit)->max_speed); 280 if (err < 0) 281 return err; 282 283 /* Register the isochronous channel for transmitting stream. */ 284 reg = cpu_to_be32(tscm->tx_resources.channel); 285 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 286 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH, 287 ®, sizeof(reg), 0); 288 if (err < 0) 289 goto error; 290 291 /* Unknown */ 292 reg = cpu_to_be32(0x00000002); 293 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 294 TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN, 295 ®, sizeof(reg), 0); 296 if (err < 0) 297 goto error; 298 299 /* Register the isochronous channel for receiving stream. */ 300 reg = cpu_to_be32(tscm->rx_resources.channel); 301 err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, 302 TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH, 303 ®, sizeof(reg), 0); 304 if (err < 0) 305 goto error; 306 307 return 0; 308 error: 309 release_resources(tscm); 310 return err; 311 } 312 313 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) 314 { 315 unsigned int pcm_channels; 316 int err; 317 318 /* For out-stream. */ 319 err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit); 320 if (err < 0) 321 return err; 322 pcm_channels = tscm->spec->pcm_playback_analog_channels; 323 if (tscm->spec->has_adat) 324 pcm_channels += 8; 325 if (tscm->spec->has_spdif) 326 pcm_channels += 2; 327 err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM, 328 pcm_channels); 329 if (err < 0) 330 return err; 331 332 /* For in-stream. */ 333 err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit); 334 if (err < 0) 335 return err; 336 pcm_channels = tscm->spec->pcm_capture_analog_channels; 337 if (tscm->spec->has_adat) 338 pcm_channels += 8; 339 if (tscm->spec->has_spdif) 340 pcm_channels += 2; 341 err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM, 342 pcm_channels); 343 if (err < 0) 344 amdtp_stream_destroy(&tscm->rx_stream); 345 346 return 0; 347 } 348 349 /* At bus reset, streaming is stopped and some registers are clear. */ 350 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) 351 { 352 amdtp_stream_pcm_abort(&tscm->tx_stream); 353 amdtp_stream_stop(&tscm->tx_stream); 354 355 amdtp_stream_pcm_abort(&tscm->rx_stream); 356 amdtp_stream_stop(&tscm->rx_stream); 357 } 358 359 /* 360 * This function should be called before starting streams or after stopping 361 * streams. 362 */ 363 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) 364 { 365 amdtp_stream_destroy(&tscm->rx_stream); 366 amdtp_stream_destroy(&tscm->tx_stream); 367 368 fw_iso_resources_destroy(&tscm->rx_resources); 369 fw_iso_resources_destroy(&tscm->tx_resources); 370 } 371 372 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) 373 { 374 unsigned int curr_rate; 375 int err; 376 377 if (tscm->substreams_counter == 0) 378 return 0; 379 380 err = snd_tscm_stream_get_rate(tscm, &curr_rate); 381 if (err < 0) 382 return err; 383 if (curr_rate != rate || 384 amdtp_streaming_error(&tscm->tx_stream) || 385 amdtp_streaming_error(&tscm->rx_stream)) { 386 finish_session(tscm); 387 388 amdtp_stream_stop(&tscm->tx_stream); 389 amdtp_stream_stop(&tscm->rx_stream); 390 391 release_resources(tscm); 392 } 393 394 if (!amdtp_stream_running(&tscm->tx_stream)) { 395 amdtp_stream_set_sync(CIP_SYNC_TO_DEVICE, 396 &tscm->tx_stream, &tscm->rx_stream); 397 err = keep_resources(tscm, rate); 398 if (err < 0) 399 goto error; 400 401 err = set_stream_formats(tscm, rate); 402 if (err < 0) 403 goto error; 404 405 err = begin_session(tscm); 406 if (err < 0) 407 goto error; 408 409 err = amdtp_stream_start(&tscm->tx_stream, 410 tscm->tx_resources.channel, 411 fw_parent_device(tscm->unit)->max_speed); 412 if (err < 0) 413 goto error; 414 415 if (!amdtp_stream_wait_callback(&tscm->tx_stream, 416 CALLBACK_TIMEOUT)) { 417 err = -ETIMEDOUT; 418 goto error; 419 } 420 } 421 422 if (!amdtp_stream_running(&tscm->rx_stream)) { 423 err = amdtp_stream_start(&tscm->rx_stream, 424 tscm->rx_resources.channel, 425 fw_parent_device(tscm->unit)->max_speed); 426 if (err < 0) 427 goto error; 428 429 if (!amdtp_stream_wait_callback(&tscm->rx_stream, 430 CALLBACK_TIMEOUT)) { 431 err = -ETIMEDOUT; 432 goto error; 433 } 434 } 435 436 return 0; 437 error: 438 amdtp_stream_stop(&tscm->tx_stream); 439 amdtp_stream_stop(&tscm->rx_stream); 440 441 finish_session(tscm); 442 release_resources(tscm); 443 444 return err; 445 } 446 447 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) 448 { 449 if (tscm->substreams_counter > 0) 450 return; 451 452 amdtp_stream_stop(&tscm->tx_stream); 453 amdtp_stream_stop(&tscm->rx_stream); 454 455 finish_session(tscm); 456 release_resources(tscm); 457 } 458 459 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) 460 { 461 tscm->dev_lock_changed = true; 462 wake_up(&tscm->hwdep_wait); 463 } 464 465 int snd_tscm_stream_lock_try(struct snd_tscm *tscm) 466 { 467 int err; 468 469 spin_lock_irq(&tscm->lock); 470 471 /* user land lock this */ 472 if (tscm->dev_lock_count < 0) { 473 err = -EBUSY; 474 goto end; 475 } 476 477 /* this is the first time */ 478 if (tscm->dev_lock_count++ == 0) 479 snd_tscm_stream_lock_changed(tscm); 480 err = 0; 481 end: 482 spin_unlock_irq(&tscm->lock); 483 return err; 484 } 485 486 void snd_tscm_stream_lock_release(struct snd_tscm *tscm) 487 { 488 spin_lock_irq(&tscm->lock); 489 490 if (WARN_ON(tscm->dev_lock_count <= 0)) 491 goto end; 492 if (--tscm->dev_lock_count == 0) 493 snd_tscm_stream_lock_changed(tscm); 494 end: 495 spin_unlock_irq(&tscm->lock); 496 } 497