.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * bebob_stream.c - a part of driver for BeBoB based devices |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2013-2014 Takashi Sakamoto |
---|
5 | | - * |
---|
6 | | - * Licensed under the terms of the GNU General Public License, version 2. |
---|
7 | 6 | */ |
---|
8 | 7 | |
---|
9 | 8 | #include "./bebob.h" |
---|
10 | 9 | |
---|
11 | | -#define CALLBACK_TIMEOUT 2000 |
---|
| 10 | +#define CALLBACK_TIMEOUT 2500 |
---|
12 | 11 | #define FW_ISO_RESOURCE_DELAY 1000 |
---|
13 | 12 | |
---|
14 | 13 | /* |
---|
.. | .. |
---|
376 | 375 | } |
---|
377 | 376 | |
---|
378 | 377 | static int |
---|
379 | | -init_both_connections(struct snd_bebob *bebob) |
---|
380 | | -{ |
---|
381 | | - int err; |
---|
382 | | - |
---|
383 | | - err = cmp_connection_init(&bebob->in_conn, |
---|
384 | | - bebob->unit, CMP_INPUT, 0); |
---|
385 | | - if (err < 0) |
---|
386 | | - goto end; |
---|
387 | | - |
---|
388 | | - err = cmp_connection_init(&bebob->out_conn, |
---|
389 | | - bebob->unit, CMP_OUTPUT, 0); |
---|
390 | | - if (err < 0) |
---|
391 | | - cmp_connection_destroy(&bebob->in_conn); |
---|
392 | | -end: |
---|
393 | | - return err; |
---|
394 | | -} |
---|
395 | | - |
---|
396 | | -static int |
---|
397 | 378 | check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) |
---|
398 | 379 | { |
---|
399 | 380 | struct cmp_connection *conn; |
---|
.. | .. |
---|
417 | 398 | return err; |
---|
418 | 399 | } |
---|
419 | 400 | |
---|
420 | | -static int |
---|
421 | | -make_both_connections(struct snd_bebob *bebob, unsigned int rate) |
---|
422 | | -{ |
---|
423 | | - int index, pcm_channels, midi_channels, err = 0; |
---|
424 | | - |
---|
425 | | - if (bebob->connected) |
---|
426 | | - goto end; |
---|
427 | | - |
---|
428 | | - /* confirm params for both streams */ |
---|
429 | | - err = get_formation_index(rate, &index); |
---|
430 | | - if (err < 0) |
---|
431 | | - goto end; |
---|
432 | | - pcm_channels = bebob->tx_stream_formations[index].pcm; |
---|
433 | | - midi_channels = bebob->tx_stream_formations[index].midi; |
---|
434 | | - err = amdtp_am824_set_parameters(&bebob->tx_stream, rate, |
---|
435 | | - pcm_channels, midi_channels * 8, |
---|
436 | | - false); |
---|
437 | | - if (err < 0) |
---|
438 | | - goto end; |
---|
439 | | - |
---|
440 | | - pcm_channels = bebob->rx_stream_formations[index].pcm; |
---|
441 | | - midi_channels = bebob->rx_stream_formations[index].midi; |
---|
442 | | - err = amdtp_am824_set_parameters(&bebob->rx_stream, rate, |
---|
443 | | - pcm_channels, midi_channels * 8, |
---|
444 | | - false); |
---|
445 | | - if (err < 0) |
---|
446 | | - goto end; |
---|
447 | | - |
---|
448 | | - /* establish connections for both streams */ |
---|
449 | | - err = cmp_connection_establish(&bebob->out_conn, |
---|
450 | | - amdtp_stream_get_max_payload(&bebob->tx_stream)); |
---|
451 | | - if (err < 0) |
---|
452 | | - goto end; |
---|
453 | | - err = cmp_connection_establish(&bebob->in_conn, |
---|
454 | | - amdtp_stream_get_max_payload(&bebob->rx_stream)); |
---|
455 | | - if (err < 0) { |
---|
456 | | - cmp_connection_break(&bebob->out_conn); |
---|
457 | | - goto end; |
---|
458 | | - } |
---|
459 | | - |
---|
460 | | - bebob->connected = true; |
---|
461 | | -end: |
---|
462 | | - return err; |
---|
463 | | -} |
---|
464 | | - |
---|
465 | | -static void |
---|
466 | | -break_both_connections(struct snd_bebob *bebob) |
---|
| 401 | +static void break_both_connections(struct snd_bebob *bebob) |
---|
467 | 402 | { |
---|
468 | 403 | cmp_connection_break(&bebob->in_conn); |
---|
469 | 404 | cmp_connection_break(&bebob->out_conn); |
---|
470 | 405 | |
---|
471 | | - bebob->connected = false; |
---|
472 | | - |
---|
473 | | - /* These models seems to be in transition state for a longer time. */ |
---|
474 | | - if (bebob->maudio_special_quirk != NULL) |
---|
475 | | - msleep(200); |
---|
| 406 | + // These models seem to be in transition state for a longer time. When |
---|
| 407 | + // accessing in the state, any transactions is corrupted. In the worst |
---|
| 408 | + // case, the device is going to reboot. |
---|
| 409 | + if (bebob->version < 2) |
---|
| 410 | + msleep(600); |
---|
476 | 411 | } |
---|
477 | 412 | |
---|
478 | | -static void |
---|
479 | | -destroy_both_connections(struct snd_bebob *bebob) |
---|
480 | | -{ |
---|
481 | | - cmp_connection_destroy(&bebob->in_conn); |
---|
482 | | - cmp_connection_destroy(&bebob->out_conn); |
---|
483 | | -} |
---|
484 | | - |
---|
485 | | -static int |
---|
486 | | -start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream, |
---|
487 | | - unsigned int rate) |
---|
| 413 | +static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) |
---|
488 | 414 | { |
---|
489 | 415 | struct cmp_connection *conn; |
---|
490 | 416 | int err = 0; |
---|
.. | .. |
---|
494 | 420 | else |
---|
495 | 421 | conn = &bebob->out_conn; |
---|
496 | 422 | |
---|
497 | | - /* channel mapping */ |
---|
| 423 | + // channel mapping. |
---|
498 | 424 | if (bebob->maudio_special_quirk == NULL) { |
---|
499 | 425 | err = map_data_channels(bebob, stream); |
---|
500 | 426 | if (err < 0) |
---|
501 | | - goto end; |
---|
| 427 | + return err; |
---|
502 | 428 | } |
---|
503 | 429 | |
---|
504 | | - /* start amdtp stream */ |
---|
505 | | - err = amdtp_stream_start(stream, |
---|
506 | | - conn->resources.channel, |
---|
507 | | - conn->speed); |
---|
508 | | -end: |
---|
509 | | - return err; |
---|
| 430 | + err = cmp_connection_establish(conn); |
---|
| 431 | + if (err < 0) |
---|
| 432 | + return err; |
---|
| 433 | + |
---|
| 434 | + return amdtp_domain_add_stream(&bebob->domain, stream, |
---|
| 435 | + conn->resources.channel, conn->speed); |
---|
| 436 | +} |
---|
| 437 | + |
---|
| 438 | +static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) |
---|
| 439 | +{ |
---|
| 440 | + enum amdtp_stream_direction dir_stream; |
---|
| 441 | + struct cmp_connection *conn; |
---|
| 442 | + enum cmp_direction dir_conn; |
---|
| 443 | + int err; |
---|
| 444 | + |
---|
| 445 | + if (stream == &bebob->tx_stream) { |
---|
| 446 | + dir_stream = AMDTP_IN_STREAM; |
---|
| 447 | + conn = &bebob->out_conn; |
---|
| 448 | + dir_conn = CMP_OUTPUT; |
---|
| 449 | + } else { |
---|
| 450 | + dir_stream = AMDTP_OUT_STREAM; |
---|
| 451 | + conn = &bebob->in_conn; |
---|
| 452 | + dir_conn = CMP_INPUT; |
---|
| 453 | + } |
---|
| 454 | + |
---|
| 455 | + err = cmp_connection_init(conn, bebob->unit, dir_conn, 0); |
---|
| 456 | + if (err < 0) |
---|
| 457 | + return err; |
---|
| 458 | + |
---|
| 459 | + err = amdtp_am824_init(stream, bebob->unit, dir_stream, CIP_BLOCKING); |
---|
| 460 | + if (err < 0) { |
---|
| 461 | + cmp_connection_destroy(conn); |
---|
| 462 | + return err; |
---|
| 463 | + } |
---|
| 464 | + |
---|
| 465 | + if (stream == &bebob->tx_stream) { |
---|
| 466 | + // BeBoB v3 transfers packets with these qurks: |
---|
| 467 | + // - In the beginning of streaming, the value of dbc is |
---|
| 468 | + // incremented even if no data blocks are transferred. |
---|
| 469 | + // - The value of dbc is reset suddenly. |
---|
| 470 | + if (bebob->version > 2) |
---|
| 471 | + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | |
---|
| 472 | + CIP_SKIP_DBC_ZERO_CHECK; |
---|
| 473 | + |
---|
| 474 | + // At high sampling rate, M-Audio special firmware transmits |
---|
| 475 | + // empty packet with the value of dbc incremented by 8 but the |
---|
| 476 | + // others are valid to IEC 61883-1. |
---|
| 477 | + if (bebob->maudio_special_quirk) |
---|
| 478 | + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; |
---|
| 479 | + } |
---|
| 480 | + |
---|
| 481 | + return 0; |
---|
| 482 | +} |
---|
| 483 | + |
---|
| 484 | +static void destroy_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) |
---|
| 485 | +{ |
---|
| 486 | + amdtp_stream_destroy(stream); |
---|
| 487 | + |
---|
| 488 | + if (stream == &bebob->tx_stream) |
---|
| 489 | + cmp_connection_destroy(&bebob->out_conn); |
---|
| 490 | + else |
---|
| 491 | + cmp_connection_destroy(&bebob->in_conn); |
---|
510 | 492 | } |
---|
511 | 493 | |
---|
512 | 494 | int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) |
---|
513 | 495 | { |
---|
514 | 496 | int err; |
---|
515 | 497 | |
---|
516 | | - err = init_both_connections(bebob); |
---|
| 498 | + err = init_stream(bebob, &bebob->tx_stream); |
---|
517 | 499 | if (err < 0) |
---|
518 | | - goto end; |
---|
| 500 | + return err; |
---|
519 | 501 | |
---|
520 | | - err = amdtp_am824_init(&bebob->tx_stream, bebob->unit, |
---|
521 | | - AMDTP_IN_STREAM, CIP_BLOCKING); |
---|
| 502 | + err = init_stream(bebob, &bebob->rx_stream); |
---|
522 | 503 | if (err < 0) { |
---|
523 | | - amdtp_stream_destroy(&bebob->tx_stream); |
---|
524 | | - destroy_both_connections(bebob); |
---|
525 | | - goto end; |
---|
| 504 | + destroy_stream(bebob, &bebob->tx_stream); |
---|
| 505 | + return err; |
---|
526 | 506 | } |
---|
527 | 507 | |
---|
528 | | - /* |
---|
529 | | - * BeBoB v3 transfers packets with these qurks: |
---|
530 | | - * - In the beginning of streaming, the value of dbc is incremented |
---|
531 | | - * even if no data blocks are transferred. |
---|
532 | | - * - The value of dbc is reset suddenly. |
---|
533 | | - */ |
---|
534 | | - if (bebob->version > 2) |
---|
535 | | - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | |
---|
536 | | - CIP_SKIP_DBC_ZERO_CHECK; |
---|
537 | | - |
---|
538 | | - /* |
---|
539 | | - * At high sampling rate, M-Audio special firmware transmits empty |
---|
540 | | - * packet with the value of dbc incremented by 8 but the others are |
---|
541 | | - * valid to IEC 61883-1. |
---|
542 | | - */ |
---|
543 | | - if (bebob->maudio_special_quirk) |
---|
544 | | - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; |
---|
545 | | - |
---|
546 | | - err = amdtp_am824_init(&bebob->rx_stream, bebob->unit, |
---|
547 | | - AMDTP_OUT_STREAM, CIP_BLOCKING); |
---|
| 508 | + err = amdtp_domain_init(&bebob->domain); |
---|
548 | 509 | if (err < 0) { |
---|
549 | | - amdtp_stream_destroy(&bebob->tx_stream); |
---|
550 | | - amdtp_stream_destroy(&bebob->rx_stream); |
---|
551 | | - destroy_both_connections(bebob); |
---|
| 510 | + destroy_stream(bebob, &bebob->tx_stream); |
---|
| 511 | + destroy_stream(bebob, &bebob->rx_stream); |
---|
552 | 512 | } |
---|
553 | | -end: |
---|
| 513 | + |
---|
554 | 514 | return err; |
---|
555 | 515 | } |
---|
556 | 516 | |
---|
557 | | -int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) |
---|
| 517 | +static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, |
---|
| 518 | + unsigned int rate, unsigned int index) |
---|
558 | 519 | { |
---|
559 | | - const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; |
---|
| 520 | + unsigned int pcm_channels; |
---|
| 521 | + unsigned int midi_ports; |
---|
| 522 | + struct cmp_connection *conn; |
---|
| 523 | + int err; |
---|
| 524 | + |
---|
| 525 | + if (stream == &bebob->tx_stream) { |
---|
| 526 | + pcm_channels = bebob->tx_stream_formations[index].pcm; |
---|
| 527 | + midi_ports = bebob->midi_input_ports; |
---|
| 528 | + conn = &bebob->out_conn; |
---|
| 529 | + } else { |
---|
| 530 | + pcm_channels = bebob->rx_stream_formations[index].pcm; |
---|
| 531 | + midi_ports = bebob->midi_output_ports; |
---|
| 532 | + conn = &bebob->in_conn; |
---|
| 533 | + } |
---|
| 534 | + |
---|
| 535 | + err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false); |
---|
| 536 | + if (err < 0) |
---|
| 537 | + return err; |
---|
| 538 | + |
---|
| 539 | + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); |
---|
| 540 | +} |
---|
| 541 | + |
---|
| 542 | +int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate, |
---|
| 543 | + unsigned int frames_per_period, |
---|
| 544 | + unsigned int frames_per_buffer) |
---|
| 545 | +{ |
---|
560 | 546 | unsigned int curr_rate; |
---|
561 | | - int err = 0; |
---|
| 547 | + int err; |
---|
562 | 548 | |
---|
563 | | - /* Need no substreams */ |
---|
564 | | - if (bebob->substreams_counter == 0) |
---|
565 | | - goto end; |
---|
566 | | - |
---|
567 | | - /* |
---|
568 | | - * Considering JACK/FFADO streaming: |
---|
569 | | - * TODO: This can be removed hwdep functionality becomes popular. |
---|
570 | | - */ |
---|
| 549 | + // Considering JACK/FFADO streaming: |
---|
| 550 | + // TODO: This can be removed hwdep functionality becomes popular. |
---|
571 | 551 | err = check_connection_used_by_others(bebob, &bebob->rx_stream); |
---|
572 | 552 | if (err < 0) |
---|
573 | | - goto end; |
---|
| 553 | + return err; |
---|
574 | 554 | |
---|
575 | | - /* |
---|
576 | | - * packet queueing error or detecting discontinuity |
---|
577 | | - * |
---|
578 | | - * At bus reset, connections should not be broken here. So streams need |
---|
579 | | - * to be re-started. This is a reason to use SKIP_INIT_DBC_CHECK flag. |
---|
580 | | - */ |
---|
581 | | - if (amdtp_streaming_error(&bebob->rx_stream)) |
---|
582 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
583 | | - if (amdtp_streaming_error(&bebob->tx_stream)) |
---|
584 | | - amdtp_stream_stop(&bebob->tx_stream); |
---|
585 | | - if (!amdtp_stream_running(&bebob->rx_stream) && |
---|
586 | | - !amdtp_stream_running(&bebob->tx_stream)) |
---|
587 | | - break_both_connections(bebob); |
---|
588 | | - |
---|
589 | | - /* stop streams if rate is different */ |
---|
590 | | - err = rate_spec->get(bebob, &curr_rate); |
---|
591 | | - if (err < 0) { |
---|
592 | | - dev_err(&bebob->unit->device, |
---|
593 | | - "fail to get sampling rate: %d\n", err); |
---|
594 | | - goto end; |
---|
595 | | - } |
---|
| 555 | + err = bebob->spec->rate->get(bebob, &curr_rate); |
---|
| 556 | + if (err < 0) |
---|
| 557 | + return err; |
---|
596 | 558 | if (rate == 0) |
---|
597 | 559 | rate = curr_rate; |
---|
598 | | - if (rate != curr_rate) { |
---|
599 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
600 | | - amdtp_stream_stop(&bebob->tx_stream); |
---|
| 560 | + if (curr_rate != rate) { |
---|
| 561 | + amdtp_domain_stop(&bebob->domain); |
---|
| 562 | + break_both_connections(bebob); |
---|
| 563 | + |
---|
| 564 | + cmp_connection_release(&bebob->out_conn); |
---|
| 565 | + cmp_connection_release(&bebob->in_conn); |
---|
| 566 | + } |
---|
| 567 | + |
---|
| 568 | + if (bebob->substreams_counter == 0 || curr_rate != rate) { |
---|
| 569 | + unsigned int index; |
---|
| 570 | + |
---|
| 571 | + // NOTE: |
---|
| 572 | + // If establishing connections at first, Yamaha GO46 |
---|
| 573 | + // (and maybe Terratec X24) don't generate sound. |
---|
| 574 | + // |
---|
| 575 | + // For firmware customized by M-Audio, refer to next NOTE. |
---|
| 576 | + err = bebob->spec->rate->set(bebob, rate); |
---|
| 577 | + if (err < 0) { |
---|
| 578 | + dev_err(&bebob->unit->device, |
---|
| 579 | + "fail to set sampling rate: %d\n", |
---|
| 580 | + err); |
---|
| 581 | + return err; |
---|
| 582 | + } |
---|
| 583 | + |
---|
| 584 | + err = get_formation_index(rate, &index); |
---|
| 585 | + if (err < 0) |
---|
| 586 | + return err; |
---|
| 587 | + |
---|
| 588 | + err = keep_resources(bebob, &bebob->tx_stream, rate, index); |
---|
| 589 | + if (err < 0) |
---|
| 590 | + return err; |
---|
| 591 | + |
---|
| 592 | + err = keep_resources(bebob, &bebob->rx_stream, rate, index); |
---|
| 593 | + if (err < 0) { |
---|
| 594 | + cmp_connection_release(&bebob->out_conn); |
---|
| 595 | + return err; |
---|
| 596 | + } |
---|
| 597 | + |
---|
| 598 | + err = amdtp_domain_set_events_per_period(&bebob->domain, |
---|
| 599 | + frames_per_period, frames_per_buffer); |
---|
| 600 | + if (err < 0) { |
---|
| 601 | + cmp_connection_release(&bebob->out_conn); |
---|
| 602 | + cmp_connection_release(&bebob->in_conn); |
---|
| 603 | + return err; |
---|
| 604 | + } |
---|
| 605 | + } |
---|
| 606 | + |
---|
| 607 | + return 0; |
---|
| 608 | +} |
---|
| 609 | + |
---|
| 610 | +int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) |
---|
| 611 | +{ |
---|
| 612 | + int err; |
---|
| 613 | + |
---|
| 614 | + // Need no substreams. |
---|
| 615 | + if (bebob->substreams_counter == 0) |
---|
| 616 | + return -EIO; |
---|
| 617 | + |
---|
| 618 | + // packet queueing error or detecting discontinuity |
---|
| 619 | + if (amdtp_streaming_error(&bebob->rx_stream) || |
---|
| 620 | + amdtp_streaming_error(&bebob->tx_stream)) { |
---|
| 621 | + amdtp_domain_stop(&bebob->domain); |
---|
601 | 622 | break_both_connections(bebob); |
---|
602 | 623 | } |
---|
603 | 624 | |
---|
604 | | - /* master should be always running */ |
---|
605 | 625 | if (!amdtp_stream_running(&bebob->rx_stream)) { |
---|
606 | | - /* |
---|
607 | | - * NOTE: |
---|
608 | | - * If establishing connections at first, Yamaha GO46 |
---|
609 | | - * (and maybe Terratec X24) don't generate sound. |
---|
610 | | - * |
---|
611 | | - * For firmware customized by M-Audio, refer to next NOTE. |
---|
612 | | - */ |
---|
613 | | - if (bebob->maudio_special_quirk == NULL) { |
---|
614 | | - err = rate_spec->set(bebob, rate); |
---|
615 | | - if (err < 0) { |
---|
616 | | - dev_err(&bebob->unit->device, |
---|
617 | | - "fail to set sampling rate: %d\n", |
---|
618 | | - err); |
---|
619 | | - goto end; |
---|
620 | | - } |
---|
| 626 | + enum snd_bebob_clock_type src; |
---|
| 627 | + struct amdtp_stream *master, *slave; |
---|
| 628 | + unsigned int curr_rate; |
---|
| 629 | + unsigned int ir_delay_cycle; |
---|
| 630 | + |
---|
| 631 | + if (bebob->maudio_special_quirk) { |
---|
| 632 | + err = bebob->spec->rate->get(bebob, &curr_rate); |
---|
| 633 | + if (err < 0) |
---|
| 634 | + return err; |
---|
621 | 635 | } |
---|
622 | 636 | |
---|
623 | | - err = make_both_connections(bebob, rate); |
---|
| 637 | + err = snd_bebob_stream_get_clock_src(bebob, &src); |
---|
624 | 638 | if (err < 0) |
---|
625 | | - goto end; |
---|
| 639 | + return err; |
---|
626 | 640 | |
---|
627 | | - err = start_stream(bebob, &bebob->rx_stream, rate); |
---|
628 | | - if (err < 0) { |
---|
629 | | - dev_err(&bebob->unit->device, |
---|
630 | | - "fail to run AMDTP master stream:%d\n", err); |
---|
631 | | - break_both_connections(bebob); |
---|
632 | | - goto end; |
---|
| 641 | + if (src != SND_BEBOB_CLOCK_TYPE_SYT) { |
---|
| 642 | + master = &bebob->tx_stream; |
---|
| 643 | + slave = &bebob->rx_stream; |
---|
| 644 | + } else { |
---|
| 645 | + master = &bebob->rx_stream; |
---|
| 646 | + slave = &bebob->tx_stream; |
---|
633 | 647 | } |
---|
634 | 648 | |
---|
635 | | - /* |
---|
636 | | - * NOTE: |
---|
637 | | - * The firmware customized by M-Audio uses these commands to |
---|
638 | | - * start transmitting stream. This is not usual way. |
---|
639 | | - */ |
---|
640 | | - if (bebob->maudio_special_quirk != NULL) { |
---|
641 | | - err = rate_spec->set(bebob, rate); |
---|
| 649 | + err = start_stream(bebob, master); |
---|
| 650 | + if (err < 0) |
---|
| 651 | + goto error; |
---|
| 652 | + |
---|
| 653 | + err = start_stream(bebob, slave); |
---|
| 654 | + if (err < 0) |
---|
| 655 | + goto error; |
---|
| 656 | + |
---|
| 657 | + // The device postpones start of transmission mostly for 1 sec |
---|
| 658 | + // after receives packets firstly. For safe, IR context starts |
---|
| 659 | + // 0.4 sec (=3200 cycles) later to version 1 or 2 firmware, |
---|
| 660 | + // 2.0 sec (=16000 cycles) for version 3 firmware. This is |
---|
| 661 | + // within 2.5 sec (=CALLBACK_TIMEOUT). |
---|
| 662 | + // Furthermore, some devices transfer isoc packets with |
---|
| 663 | + // discontinuous counter in the beginning of packet streaming. |
---|
| 664 | + // The delay has an effect to avoid detection of this |
---|
| 665 | + // discontinuity. |
---|
| 666 | + if (bebob->version < 2) |
---|
| 667 | + ir_delay_cycle = 3200; |
---|
| 668 | + else |
---|
| 669 | + ir_delay_cycle = 16000; |
---|
| 670 | + err = amdtp_domain_start(&bebob->domain, ir_delay_cycle); |
---|
| 671 | + if (err < 0) |
---|
| 672 | + goto error; |
---|
| 673 | + |
---|
| 674 | + // NOTE: |
---|
| 675 | + // The firmware customized by M-Audio uses these commands to |
---|
| 676 | + // start transmitting stream. This is not usual way. |
---|
| 677 | + if (bebob->maudio_special_quirk) { |
---|
| 678 | + err = bebob->spec->rate->set(bebob, curr_rate); |
---|
642 | 679 | if (err < 0) { |
---|
643 | 680 | dev_err(&bebob->unit->device, |
---|
644 | 681 | "fail to ensure sampling rate: %d\n", |
---|
645 | 682 | err); |
---|
646 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
647 | | - break_both_connections(bebob); |
---|
648 | | - goto end; |
---|
| 683 | + goto error; |
---|
649 | 684 | } |
---|
650 | 685 | } |
---|
651 | 686 | |
---|
652 | | - /* wait first callback */ |
---|
653 | 687 | if (!amdtp_stream_wait_callback(&bebob->rx_stream, |
---|
| 688 | + CALLBACK_TIMEOUT) || |
---|
| 689 | + !amdtp_stream_wait_callback(&bebob->tx_stream, |
---|
654 | 690 | CALLBACK_TIMEOUT)) { |
---|
655 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
656 | | - break_both_connections(bebob); |
---|
657 | 691 | err = -ETIMEDOUT; |
---|
658 | | - goto end; |
---|
| 692 | + goto error; |
---|
659 | 693 | } |
---|
660 | 694 | } |
---|
661 | 695 | |
---|
662 | | - /* start slave if needed */ |
---|
663 | | - if (!amdtp_stream_running(&bebob->tx_stream)) { |
---|
664 | | - err = start_stream(bebob, &bebob->tx_stream, rate); |
---|
665 | | - if (err < 0) { |
---|
666 | | - dev_err(&bebob->unit->device, |
---|
667 | | - "fail to run AMDTP slave stream:%d\n", err); |
---|
668 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
669 | | - break_both_connections(bebob); |
---|
670 | | - goto end; |
---|
671 | | - } |
---|
672 | | - |
---|
673 | | - /* wait first callback */ |
---|
674 | | - if (!amdtp_stream_wait_callback(&bebob->tx_stream, |
---|
675 | | - CALLBACK_TIMEOUT)) { |
---|
676 | | - amdtp_stream_stop(&bebob->tx_stream); |
---|
677 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
678 | | - break_both_connections(bebob); |
---|
679 | | - err = -ETIMEDOUT; |
---|
680 | | - } |
---|
681 | | - } |
---|
682 | | -end: |
---|
| 696 | + return 0; |
---|
| 697 | +error: |
---|
| 698 | + amdtp_domain_stop(&bebob->domain); |
---|
| 699 | + break_both_connections(bebob); |
---|
683 | 700 | return err; |
---|
684 | 701 | } |
---|
685 | 702 | |
---|
686 | 703 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) |
---|
687 | 704 | { |
---|
688 | 705 | if (bebob->substreams_counter == 0) { |
---|
689 | | - amdtp_stream_pcm_abort(&bebob->rx_stream); |
---|
690 | | - amdtp_stream_stop(&bebob->rx_stream); |
---|
691 | | - |
---|
692 | | - amdtp_stream_pcm_abort(&bebob->tx_stream); |
---|
693 | | - amdtp_stream_stop(&bebob->tx_stream); |
---|
694 | | - |
---|
| 706 | + amdtp_domain_stop(&bebob->domain); |
---|
695 | 707 | break_both_connections(bebob); |
---|
| 708 | + |
---|
| 709 | + cmp_connection_release(&bebob->out_conn); |
---|
| 710 | + cmp_connection_release(&bebob->in_conn); |
---|
696 | 711 | } |
---|
697 | 712 | } |
---|
698 | 713 | |
---|
.. | .. |
---|
702 | 717 | */ |
---|
703 | 718 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) |
---|
704 | 719 | { |
---|
705 | | - amdtp_stream_destroy(&bebob->rx_stream); |
---|
706 | | - amdtp_stream_destroy(&bebob->tx_stream); |
---|
| 720 | + amdtp_domain_destroy(&bebob->domain); |
---|
707 | 721 | |
---|
708 | | - destroy_both_connections(bebob); |
---|
| 722 | + destroy_stream(bebob, &bebob->tx_stream); |
---|
| 723 | + destroy_stream(bebob, &bebob->rx_stream); |
---|
709 | 724 | } |
---|
710 | 725 | |
---|
711 | 726 | /* |
---|