| .. | .. |
|---|
| 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 | /* |
|---|