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