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->rx_stream) || 385 amdtp_streaming_error(&tscm->tx_stream)) { 386 finish_session(tscm); 387 388 amdtp_stream_stop(&tscm->rx_stream); 389 amdtp_stream_stop(&tscm->tx_stream); 390 391 release_resources(tscm); 392 } 393 394 if (!amdtp_stream_running(&tscm->rx_stream)) { 395 err = keep_resources(tscm, rate); 396 if (err < 0) 397 goto error; 398 399 err = set_stream_formats(tscm, rate); 400 if (err < 0) 401 goto error; 402 403 err = begin_session(tscm); 404 if (err < 0) 405 goto error; 406 407 err = amdtp_stream_start(&tscm->rx_stream, 408 tscm->rx_resources.channel, 409 fw_parent_device(tscm->unit)->max_speed); 410 if (err < 0) 411 goto error; 412 413 if (!amdtp_stream_wait_callback(&tscm->rx_stream, 414 CALLBACK_TIMEOUT)) { 415 err = -ETIMEDOUT; 416 goto error; 417 } 418 } 419 420 if (!amdtp_stream_running(&tscm->tx_stream)) { 421 err = amdtp_stream_start(&tscm->tx_stream, 422 tscm->tx_resources.channel, 423 fw_parent_device(tscm->unit)->max_speed); 424 if (err < 0) 425 goto error; 426 427 if (!amdtp_stream_wait_callback(&tscm->tx_stream, 428 CALLBACK_TIMEOUT)) { 429 err = -ETIMEDOUT; 430 goto error; 431 } 432 } 433 434 return 0; 435 error: 436 amdtp_stream_stop(&tscm->rx_stream); 437 amdtp_stream_stop(&tscm->tx_stream); 438 439 finish_session(tscm); 440 release_resources(tscm); 441 442 return err; 443 } 444 445 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) 446 { 447 if (tscm->substreams_counter > 0) 448 return; 449 450 amdtp_stream_stop(&tscm->tx_stream); 451 amdtp_stream_stop(&tscm->rx_stream); 452 453 finish_session(tscm); 454 release_resources(tscm); 455 } 456 457 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm) 458 { 459 tscm->dev_lock_changed = true; 460 wake_up(&tscm->hwdep_wait); 461 } 462 463 int snd_tscm_stream_lock_try(struct snd_tscm *tscm) 464 { 465 int err; 466 467 spin_lock_irq(&tscm->lock); 468 469 /* user land lock this */ 470 if (tscm->dev_lock_count < 0) { 471 err = -EBUSY; 472 goto end; 473 } 474 475 /* this is the first time */ 476 if (tscm->dev_lock_count++ == 0) 477 snd_tscm_stream_lock_changed(tscm); 478 err = 0; 479 end: 480 spin_unlock_irq(&tscm->lock); 481 return err; 482 } 483 484 void snd_tscm_stream_lock_release(struct snd_tscm *tscm) 485 { 486 spin_lock_irq(&tscm->lock); 487 488 if (WARN_ON(tscm->dev_lock_count <= 0)) 489 goto end; 490 if (--tscm->dev_lock_count == 0) 491 snd_tscm_stream_lock_changed(tscm); 492 end: 493 spin_unlock_irq(&tscm->lock); 494 } 495