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