.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | | - * This program is free software; you can redistribute it and/or modify |
---|
3 | | - * it under the terms of the GNU General Public License as published by |
---|
4 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
5 | | - * (at your option) any later version. |
---|
6 | | - * |
---|
7 | | - * This program is distributed in the hope that it will be useful, |
---|
8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | | - * GNU General Public License for more details. |
---|
11 | | - * |
---|
12 | | - * You should have received a copy of the GNU General Public License |
---|
13 | | - * along with this program; if not, write to the Free Software |
---|
14 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
15 | 3 | */ |
---|
16 | 4 | |
---|
17 | 5 | #include <linux/init.h> |
---|
.. | .. |
---|
26 | 14 | #include <sound/pcm.h> |
---|
27 | 15 | #include <sound/pcm_params.h> |
---|
28 | 16 | |
---|
| 17 | +#include <trace/hooks/sound.h> |
---|
| 18 | + |
---|
29 | 19 | #include "usbaudio.h" |
---|
30 | 20 | #include "card.h" |
---|
31 | 21 | #include "quirks.h" |
---|
.. | .. |
---|
35 | 25 | #include "pcm.h" |
---|
36 | 26 | #include "clock.h" |
---|
37 | 27 | #include "power.h" |
---|
| 28 | +#include "media.h" |
---|
38 | 29 | |
---|
39 | 30 | #define SUBSTREAM_FLAG_DATA_EP_STARTED 0 |
---|
40 | 31 | #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 |
---|
.. | .. |
---|
145 | 136 | found = fp; |
---|
146 | 137 | cur_attr = attr; |
---|
147 | 138 | } |
---|
| 139 | + |
---|
| 140 | + snd_vendor_set_pcm_binterval(fp, found, &cur_attr, &attr); |
---|
148 | 141 | } |
---|
149 | 142 | return found; |
---|
150 | 143 | } |
---|
.. | .. |
---|
334 | 327 | return 0; |
---|
335 | 328 | } |
---|
336 | 329 | |
---|
337 | | -static void stop_endpoints(struct snd_usb_substream *subs, bool wait) |
---|
| 330 | +static void sync_pending_stops(struct snd_usb_substream *subs) |
---|
338 | 331 | { |
---|
339 | | - if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { |
---|
340 | | - snd_usb_endpoint_stop(subs->sync_endpoint); |
---|
341 | | - if (wait) |
---|
342 | | - snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); |
---|
343 | | - } |
---|
| 332 | + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); |
---|
| 333 | + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); |
---|
| 334 | +} |
---|
344 | 335 | |
---|
345 | | - if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { |
---|
| 336 | +static void stop_endpoints(struct snd_usb_substream *subs) |
---|
| 337 | +{ |
---|
| 338 | + if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) |
---|
| 339 | + snd_usb_endpoint_stop(subs->sync_endpoint); |
---|
| 340 | + |
---|
| 341 | + if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) |
---|
346 | 342 | snd_usb_endpoint_stop(subs->data_endpoint); |
---|
347 | | - if (wait) |
---|
348 | | - snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); |
---|
349 | | - } |
---|
| 343 | +} |
---|
| 344 | + |
---|
| 345 | +/* PCM sync_stop callback */ |
---|
| 346 | +static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) |
---|
| 347 | +{ |
---|
| 348 | + struct snd_usb_substream *subs = substream->runtime->private_data; |
---|
| 349 | + |
---|
| 350 | + sync_pending_stops(subs); |
---|
| 351 | + return 0; |
---|
350 | 352 | } |
---|
351 | 353 | |
---|
352 | 354 | static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, |
---|
.. | .. |
---|
425 | 427 | ep = 0x81; |
---|
426 | 428 | ifnum = 1; |
---|
427 | 429 | goto add_sync_ep_from_ifnum; |
---|
| 430 | + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */ |
---|
| 431 | + /* MicroBook IIc */ |
---|
| 432 | + if (altsd->bInterfaceClass == USB_CLASS_AUDIO) |
---|
| 433 | + return 0; |
---|
| 434 | + |
---|
| 435 | + /* MicroBook II */ |
---|
| 436 | + ep = 0x84; |
---|
| 437 | + ifnum = 0; |
---|
| 438 | + goto add_sync_ep_from_ifnum; |
---|
| 439 | + case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ |
---|
| 440 | + case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */ |
---|
| 441 | + case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */ |
---|
| 442 | + case USB_ID(0x0499, 0x172f): /* Steinberg UR22C */ |
---|
| 443 | + case USB_ID(0x0d9a, 0x00df): /* RTX6001 */ |
---|
| 444 | + ep = 0x81; |
---|
| 445 | + ifnum = 2; |
---|
| 446 | + goto add_sync_ep_from_ifnum; |
---|
| 447 | + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ |
---|
| 448 | + case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */ |
---|
| 449 | + ep = 0x82; |
---|
| 450 | + ifnum = 0; |
---|
| 451 | + goto add_sync_ep_from_ifnum; |
---|
428 | 452 | case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ |
---|
429 | 453 | /* BOSS Katana amplifiers do not need quirks */ |
---|
430 | 454 | return 0; |
---|
.. | .. |
---|
458 | 482 | SND_USB_ENDPOINT_TYPE_DATA); |
---|
459 | 483 | if (!subs->sync_endpoint) |
---|
460 | 484 | return -EINVAL; |
---|
| 485 | + |
---|
| 486 | + subs->sync_endpoint->is_implicit_feedback = 1; |
---|
461 | 487 | |
---|
462 | 488 | subs->data_endpoint->sync_master = subs->sync_endpoint; |
---|
463 | 489 | |
---|
.. | .. |
---|
557 | 583 | implicit_fb ? |
---|
558 | 584 | SND_USB_ENDPOINT_TYPE_DATA : |
---|
559 | 585 | SND_USB_ENDPOINT_TYPE_SYNC); |
---|
| 586 | + |
---|
560 | 587 | if (!subs->sync_endpoint) { |
---|
561 | 588 | if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) |
---|
562 | 589 | return 0; |
---|
563 | 590 | return -EINVAL; |
---|
564 | 591 | } |
---|
| 592 | + |
---|
| 593 | + subs->sync_endpoint->is_implicit_feedback = implicit_fb; |
---|
565 | 594 | |
---|
566 | 595 | subs->data_endpoint->sync_master = subs->sync_endpoint; |
---|
567 | 596 | |
---|
.. | .. |
---|
623 | 652 | } |
---|
624 | 653 | dev_dbg(&dev->dev, "setting usb interface %d:%d\n", |
---|
625 | 654 | fmt->iface, fmt->altsetting); |
---|
| 655 | + err = snd_vendor_set_pcm_intf(iface, fmt->iface, |
---|
| 656 | + fmt->altsetting, subs->direction); |
---|
| 657 | + if (err) |
---|
| 658 | + return err; |
---|
626 | 659 | snd_usb_set_interface_quirk(dev); |
---|
627 | 660 | } |
---|
628 | 661 | |
---|
.. | .. |
---|
650 | 683 | return 0; |
---|
651 | 684 | } |
---|
652 | 685 | |
---|
653 | | -/** |
---|
654 | | - * snd_usb_enable_audio_stream - Enable/disable the specified usb substream. |
---|
655 | | - * @subs: pointer to the usb substream. |
---|
656 | | - * @datainterval: data packet interval. |
---|
657 | | - * @enable: if true, enable the usb substream. Else disable. |
---|
658 | | - */ |
---|
| 686 | +static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state); |
---|
| 687 | + |
---|
659 | 688 | int snd_usb_enable_audio_stream(struct snd_usb_substream *subs, |
---|
660 | 689 | int datainterval, bool enable) |
---|
661 | 690 | { |
---|
.. | .. |
---|
663 | 692 | struct usb_host_interface *alts; |
---|
664 | 693 | struct usb_interface *iface; |
---|
665 | 694 | int ret; |
---|
666 | | - |
---|
667 | | - if (!subs || !subs->stream) |
---|
668 | | - return -EINVAL; |
---|
669 | 695 | |
---|
670 | 696 | if (!enable) { |
---|
671 | 697 | if (subs->interface >= 0) { |
---|
.. | .. |
---|
680 | 706 | } |
---|
681 | 707 | |
---|
682 | 708 | snd_usb_autoresume(subs->stream->chip); |
---|
| 709 | + |
---|
| 710 | + ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); |
---|
| 711 | + if (ret < 0) |
---|
| 712 | + return ret; |
---|
| 713 | + |
---|
683 | 714 | if (datainterval != -EINVAL) |
---|
684 | 715 | fmt = find_format_and_si(subs, datainterval); |
---|
685 | 716 | else |
---|
686 | 717 | fmt = find_format(subs); |
---|
687 | 718 | if (!fmt) { |
---|
688 | | - dev_dbg(&subs->dev->dev, |
---|
| 719 | + dev_err(&subs->dev->dev, |
---|
689 | 720 | "cannot set format: format = %#x, rate = %d, channels = %d\n", |
---|
690 | 721 | subs->pcm_format, subs->cur_rate, subs->channels); |
---|
691 | 722 | return -EINVAL; |
---|
.. | .. |
---|
693 | 724 | |
---|
694 | 725 | subs->altset_idx = 0; |
---|
695 | 726 | subs->interface = -1; |
---|
696 | | - |
---|
697 | | - if (!subs->stream->chip) |
---|
698 | | - return -EINVAL; |
---|
699 | | - |
---|
700 | 727 | if (atomic_read(&subs->stream->chip->shutdown)) { |
---|
701 | 728 | ret = -ENODEV; |
---|
702 | 729 | } else { |
---|
703 | 730 | ret = set_format(subs, fmt); |
---|
704 | 731 | if (ret < 0) |
---|
705 | 732 | return ret; |
---|
706 | | - |
---|
707 | | - if (!subs->cur_audiofmt) |
---|
708 | | - return -EINVAL; |
---|
709 | 733 | |
---|
710 | 734 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); |
---|
711 | 735 | if (!iface) { |
---|
.. | .. |
---|
861 | 885 | int ret; |
---|
862 | 886 | |
---|
863 | 887 | /* format changed */ |
---|
864 | | - stop_endpoints(subs, true); |
---|
| 888 | + stop_endpoints(subs); |
---|
| 889 | + sync_pending_stops(subs); |
---|
865 | 890 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, |
---|
866 | 891 | subs->pcm_format, |
---|
867 | 892 | subs->channels, |
---|
.. | .. |
---|
945 | 970 | struct audioformat *fmt; |
---|
946 | 971 | int ret; |
---|
947 | 972 | |
---|
948 | | - if (snd_usb_use_vmalloc) |
---|
949 | | - ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
---|
950 | | - params_buffer_bytes(hw_params)); |
---|
951 | | - else |
---|
952 | | - ret = snd_pcm_lib_malloc_pages(substream, |
---|
953 | | - params_buffer_bytes(hw_params)); |
---|
954 | | - if (ret < 0) |
---|
| 973 | + ret = snd_media_start_pipeline(subs); |
---|
| 974 | + if (ret) |
---|
955 | 975 | return ret; |
---|
956 | 976 | |
---|
957 | 977 | subs->pcm_format = params_format(hw_params); |
---|
.. | .. |
---|
966 | 986 | dev_dbg(&subs->dev->dev, |
---|
967 | 987 | "cannot set format: format = %#x, rate = %d, channels = %d\n", |
---|
968 | 988 | subs->pcm_format, subs->cur_rate, subs->channels); |
---|
969 | | - return -EINVAL; |
---|
| 989 | + ret = -EINVAL; |
---|
| 990 | + goto stop_pipeline; |
---|
970 | 991 | } |
---|
971 | 992 | |
---|
972 | 993 | ret = snd_usb_lock_shutdown(subs->stream->chip); |
---|
973 | 994 | if (ret < 0) |
---|
974 | | - return ret; |
---|
| 995 | + goto stop_pipeline; |
---|
975 | 996 | |
---|
976 | 997 | ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); |
---|
977 | 998 | if (ret < 0) |
---|
.. | .. |
---|
987 | 1008 | |
---|
988 | 1009 | unlock: |
---|
989 | 1010 | snd_usb_unlock_shutdown(subs->stream->chip); |
---|
| 1011 | + if (ret < 0) |
---|
| 1012 | + goto stop_pipeline; |
---|
| 1013 | + return ret; |
---|
| 1014 | + |
---|
| 1015 | + stop_pipeline: |
---|
| 1016 | + snd_media_stop_pipeline(subs); |
---|
990 | 1017 | return ret; |
---|
991 | 1018 | } |
---|
992 | 1019 | |
---|
.. | .. |
---|
999 | 1026 | { |
---|
1000 | 1027 | struct snd_usb_substream *subs = substream->runtime->private_data; |
---|
1001 | 1028 | |
---|
| 1029 | + snd_media_stop_pipeline(subs); |
---|
1002 | 1030 | subs->cur_audiofmt = NULL; |
---|
1003 | 1031 | subs->cur_rate = 0; |
---|
1004 | 1032 | subs->period_bytes = 0; |
---|
1005 | 1033 | if (!snd_usb_lock_shutdown(subs->stream->chip)) { |
---|
1006 | | - stop_endpoints(subs, true); |
---|
| 1034 | + stop_endpoints(subs); |
---|
| 1035 | + sync_pending_stops(subs); |
---|
1007 | 1036 | snd_usb_endpoint_deactivate(subs->sync_endpoint); |
---|
1008 | 1037 | snd_usb_endpoint_deactivate(subs->data_endpoint); |
---|
1009 | 1038 | snd_usb_unlock_shutdown(subs->stream->chip); |
---|
1010 | 1039 | } |
---|
1011 | 1040 | |
---|
1012 | | - if (snd_usb_use_vmalloc) |
---|
1013 | | - return snd_pcm_lib_free_vmalloc_buffer(substream); |
---|
1014 | | - else |
---|
1015 | | - return snd_pcm_lib_free_pages(substream); |
---|
| 1041 | + return 0; |
---|
1016 | 1042 | } |
---|
1017 | 1043 | |
---|
1018 | 1044 | /* |
---|
.. | .. |
---|
1028 | 1054 | struct usb_interface *iface; |
---|
1029 | 1055 | int ret; |
---|
1030 | 1056 | |
---|
| 1057 | + ret = snd_vendor_set_pcm_buf(subs->dev, subs->cur_audiofmt->iface); |
---|
| 1058 | + if (ret) |
---|
| 1059 | + return ret; |
---|
| 1060 | + |
---|
1031 | 1061 | if (! subs->cur_audiofmt) { |
---|
1032 | 1062 | dev_err(&subs->dev->dev, "no format is specified!\n"); |
---|
1033 | 1063 | return -ENXIO; |
---|
.. | .. |
---|
1040 | 1070 | ret = -EIO; |
---|
1041 | 1071 | goto unlock; |
---|
1042 | 1072 | } |
---|
1043 | | - |
---|
1044 | | - snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); |
---|
1045 | | - snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); |
---|
1046 | 1073 | |
---|
1047 | 1074 | ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); |
---|
1048 | 1075 | if (ret < 0) |
---|
.. | .. |
---|
1063 | 1090 | subs->cur_rate); |
---|
1064 | 1091 | if (ret < 0) |
---|
1065 | 1092 | goto unlock; |
---|
| 1093 | + |
---|
| 1094 | + if (snd_vendor_get_ops()) { |
---|
| 1095 | + ret = snd_vendor_set_rate(iface, |
---|
| 1096 | + subs->cur_audiofmt->iface, |
---|
| 1097 | + subs->cur_rate, |
---|
| 1098 | + subs->cur_audiofmt->altsetting); |
---|
| 1099 | + if (!ret) { |
---|
| 1100 | + subs->need_setup_ep = false; |
---|
| 1101 | + goto unlock; |
---|
| 1102 | + } |
---|
| 1103 | + } |
---|
1066 | 1104 | |
---|
1067 | 1105 | ret = configure_endpoint(subs); |
---|
1068 | 1106 | if (ret < 0) |
---|
.. | .. |
---|
1471 | 1509 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
---|
1472 | 1510 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
1473 | 1511 | struct snd_usb_substream *subs = &as->substream[direction]; |
---|
| 1512 | + int ret; |
---|
| 1513 | + bool is_support = false; |
---|
| 1514 | + |
---|
| 1515 | + ret = snd_vendor_set_pcm_connection(subs->dev, SOUND_PCM_OPEN, |
---|
| 1516 | + direction); |
---|
| 1517 | + if (ret) |
---|
| 1518 | + return ret; |
---|
1474 | 1519 | |
---|
1475 | 1520 | subs->interface = -1; |
---|
1476 | 1521 | subs->altset_idx = 0; |
---|
.. | .. |
---|
1484 | 1529 | subs->dsd_dop.channel = 0; |
---|
1485 | 1530 | subs->dsd_dop.marker = 1; |
---|
1486 | 1531 | |
---|
1487 | | - return setup_hw_info(runtime, subs); |
---|
| 1532 | + ret = setup_hw_info(runtime, subs); |
---|
| 1533 | + if (ret == 0) { |
---|
| 1534 | + ret = snd_media_stream_init(subs, as->pcm, direction); |
---|
| 1535 | + if (ret) |
---|
| 1536 | + snd_usb_autosuspend(subs->stream->chip); |
---|
| 1537 | + } |
---|
| 1538 | + |
---|
| 1539 | + trace_android_vh_sound_usb_support_cpu_suspend(subs->dev, direction, &is_support); |
---|
| 1540 | + if (!ret && is_support) |
---|
| 1541 | + snd_usb_autosuspend(subs->stream->chip); |
---|
| 1542 | + |
---|
| 1543 | + return ret; |
---|
1488 | 1544 | } |
---|
1489 | 1545 | |
---|
1490 | 1546 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream) |
---|
.. | .. |
---|
1493 | 1549 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
---|
1494 | 1550 | struct snd_usb_substream *subs = &as->substream[direction]; |
---|
1495 | 1551 | int ret; |
---|
| 1552 | + bool is_support = false; |
---|
1496 | 1553 | |
---|
1497 | | - stop_endpoints(subs, true); |
---|
| 1554 | + ret = snd_vendor_set_pcm_connection(subs->dev, SOUND_PCM_CLOSE, |
---|
| 1555 | + direction); |
---|
| 1556 | + if (ret) |
---|
| 1557 | + return ret; |
---|
| 1558 | + |
---|
| 1559 | + trace_android_vh_sound_usb_support_cpu_suspend(subs->dev, direction, &is_support); |
---|
| 1560 | + if (!ret && is_support) |
---|
| 1561 | + snd_usb_autoresume(subs->stream->chip); |
---|
| 1562 | + |
---|
| 1563 | + snd_media_stop_pipeline(subs); |
---|
1498 | 1564 | |
---|
1499 | 1565 | if (!as->chip->keep_iface && |
---|
1500 | 1566 | subs->interface >= 0 && |
---|
1501 | 1567 | !snd_usb_lock_shutdown(subs->stream->chip)) { |
---|
1502 | 1568 | usb_set_interface(subs->dev, subs->interface, 0); |
---|
| 1569 | + ret = snd_vendor_set_pcm_intf(usb_ifnum_to_if(subs->dev, |
---|
| 1570 | + subs->interface), |
---|
| 1571 | + subs->interface, 0, |
---|
| 1572 | + direction); |
---|
| 1573 | + if (ret) |
---|
| 1574 | + return ret; |
---|
1503 | 1575 | subs->interface = -1; |
---|
1504 | 1576 | ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1); |
---|
1505 | 1577 | snd_usb_unlock_shutdown(subs->stream->chip); |
---|
.. | .. |
---|
1541 | 1613 | // continue; |
---|
1542 | 1614 | } |
---|
1543 | 1615 | bytes = urb->iso_frame_desc[i].actual_length; |
---|
| 1616 | + if (subs->stream_offset_adj > 0) { |
---|
| 1617 | + unsigned int adj = min(subs->stream_offset_adj, bytes); |
---|
| 1618 | + cp += adj; |
---|
| 1619 | + bytes -= adj; |
---|
| 1620 | + subs->stream_offset_adj -= adj; |
---|
| 1621 | + } |
---|
1544 | 1622 | frames = bytes / stride; |
---|
1545 | 1623 | if (!subs->txfr_quirk) |
---|
1546 | 1624 | bytes = frames * stride; |
---|
.. | .. |
---|
1712 | 1790 | for (i = 0; i < ctx->packets; i++) { |
---|
1713 | 1791 | if (ctx->packet_size[i]) |
---|
1714 | 1792 | counts = ctx->packet_size[i]; |
---|
| 1793 | + else if (ep->sync_master) |
---|
| 1794 | + counts = snd_usb_endpoint_slave_next_packet_size(ep); |
---|
1715 | 1795 | else |
---|
1716 | 1796 | counts = snd_usb_endpoint_next_packet_size(ep); |
---|
1717 | 1797 | |
---|
.. | .. |
---|
1815 | 1895 | int processed = urb->transfer_buffer_length / ep->stride; |
---|
1816 | 1896 | int est_delay; |
---|
1817 | 1897 | |
---|
1818 | | - /* ignore the delay accounting when procssed=0 is given, i.e. |
---|
1819 | | - * silent payloads are procssed before handling the actual data |
---|
| 1898 | + /* ignore the delay accounting when processed=0 is given, i.e. |
---|
| 1899 | + * silent payloads are processed before handling the actual data |
---|
1820 | 1900 | */ |
---|
1821 | 1901 | if (!processed) |
---|
1822 | 1902 | return; |
---|
.. | .. |
---|
1862 | 1942 | |
---|
1863 | 1943 | switch (cmd) { |
---|
1864 | 1944 | case SNDRV_PCM_TRIGGER_START: |
---|
1865 | | - case SNDRV_PCM_TRIGGER_RESUME: |
---|
1866 | 1945 | subs->trigger_tstamp_pending_update = true; |
---|
1867 | | - /* fall through */ |
---|
| 1946 | + fallthrough; |
---|
1868 | 1947 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
---|
1869 | 1948 | subs->data_endpoint->prepare_data_urb = prepare_playback_urb; |
---|
1870 | 1949 | subs->data_endpoint->retire_data_urb = retire_playback_urb; |
---|
1871 | 1950 | subs->running = 1; |
---|
1872 | 1951 | return 0; |
---|
1873 | | - case SNDRV_PCM_TRIGGER_SUSPEND: |
---|
1874 | | - stop_endpoints(subs, true); |
---|
1875 | | - subs->running = 0; |
---|
1876 | | - if (subs->stream->chip->setup_fmt_after_resume_quirk) |
---|
1877 | | - subs->need_setup_fmt = true; |
---|
1878 | | - return 0; |
---|
1879 | 1952 | case SNDRV_PCM_TRIGGER_STOP: |
---|
1880 | | - stop_endpoints(subs, false); |
---|
| 1953 | + stop_endpoints(subs); |
---|
1881 | 1954 | subs->running = 0; |
---|
1882 | 1955 | return 0; |
---|
1883 | 1956 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
---|
.. | .. |
---|
1886 | 1959 | subs->data_endpoint->retire_data_urb = retire_playback_urb; |
---|
1887 | 1960 | subs->running = 0; |
---|
1888 | 1961 | return 0; |
---|
| 1962 | + case SNDRV_PCM_TRIGGER_SUSPEND: |
---|
| 1963 | + if (subs->stream->chip->setup_fmt_after_resume_quirk) { |
---|
| 1964 | + stop_endpoints(subs); |
---|
| 1965 | + subs->need_setup_fmt = true; |
---|
| 1966 | + return 0; |
---|
| 1967 | + } |
---|
| 1968 | + break; |
---|
1889 | 1969 | } |
---|
1890 | 1970 | |
---|
1891 | 1971 | return -EINVAL; |
---|
.. | .. |
---|
1899 | 1979 | |
---|
1900 | 1980 | switch (cmd) { |
---|
1901 | 1981 | case SNDRV_PCM_TRIGGER_START: |
---|
1902 | | - case SNDRV_PCM_TRIGGER_RESUME: |
---|
1903 | 1982 | err = start_endpoints(subs); |
---|
1904 | 1983 | if (err < 0) |
---|
1905 | 1984 | return err; |
---|
.. | .. |
---|
1907 | 1986 | subs->data_endpoint->retire_data_urb = retire_capture_urb; |
---|
1908 | 1987 | subs->running = 1; |
---|
1909 | 1988 | return 0; |
---|
1910 | | - case SNDRV_PCM_TRIGGER_SUSPEND: |
---|
1911 | | - stop_endpoints(subs, true); |
---|
1912 | | - subs->running = 0; |
---|
1913 | | - if (subs->stream->chip->setup_fmt_after_resume_quirk) |
---|
1914 | | - subs->need_setup_fmt = true; |
---|
1915 | | - return 0; |
---|
1916 | 1989 | case SNDRV_PCM_TRIGGER_STOP: |
---|
1917 | | - stop_endpoints(subs, false); |
---|
| 1990 | + stop_endpoints(subs); |
---|
| 1991 | + subs->data_endpoint->retire_data_urb = NULL; |
---|
1918 | 1992 | subs->running = 0; |
---|
1919 | 1993 | return 0; |
---|
1920 | 1994 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
---|
.. | .. |
---|
1925 | 1999 | subs->data_endpoint->retire_data_urb = retire_capture_urb; |
---|
1926 | 2000 | subs->running = 1; |
---|
1927 | 2001 | return 0; |
---|
| 2002 | + case SNDRV_PCM_TRIGGER_SUSPEND: |
---|
| 2003 | + if (subs->stream->chip->setup_fmt_after_resume_quirk) { |
---|
| 2004 | + stop_endpoints(subs); |
---|
| 2005 | + subs->need_setup_fmt = true; |
---|
| 2006 | + return 0; |
---|
| 2007 | + } |
---|
| 2008 | + break; |
---|
1928 | 2009 | } |
---|
1929 | 2010 | |
---|
1930 | 2011 | return -EINVAL; |
---|
.. | .. |
---|
1933 | 2014 | static const struct snd_pcm_ops snd_usb_playback_ops = { |
---|
1934 | 2015 | .open = snd_usb_pcm_open, |
---|
1935 | 2016 | .close = snd_usb_pcm_close, |
---|
1936 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1937 | 2017 | .hw_params = snd_usb_hw_params, |
---|
1938 | 2018 | .hw_free = snd_usb_hw_free, |
---|
1939 | 2019 | .prepare = snd_usb_pcm_prepare, |
---|
1940 | 2020 | .trigger = snd_usb_substream_playback_trigger, |
---|
| 2021 | + .sync_stop = snd_usb_pcm_sync_stop, |
---|
1941 | 2022 | .pointer = snd_usb_pcm_pointer, |
---|
1942 | | - .page = snd_pcm_lib_get_vmalloc_page, |
---|
1943 | 2023 | }; |
---|
1944 | 2024 | |
---|
1945 | 2025 | static const struct snd_pcm_ops snd_usb_capture_ops = { |
---|
1946 | 2026 | .open = snd_usb_pcm_open, |
---|
1947 | 2027 | .close = snd_usb_pcm_close, |
---|
1948 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1949 | 2028 | .hw_params = snd_usb_hw_params, |
---|
1950 | 2029 | .hw_free = snd_usb_hw_free, |
---|
1951 | 2030 | .prepare = snd_usb_pcm_prepare, |
---|
1952 | 2031 | .trigger = snd_usb_substream_capture_trigger, |
---|
| 2032 | + .sync_stop = snd_usb_pcm_sync_stop, |
---|
1953 | 2033 | .pointer = snd_usb_pcm_pointer, |
---|
1954 | | - .page = snd_pcm_lib_get_vmalloc_page, |
---|
1955 | | -}; |
---|
1956 | | - |
---|
1957 | | -static const struct snd_pcm_ops snd_usb_playback_dev_ops = { |
---|
1958 | | - .open = snd_usb_pcm_open, |
---|
1959 | | - .close = snd_usb_pcm_close, |
---|
1960 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1961 | | - .hw_params = snd_usb_hw_params, |
---|
1962 | | - .hw_free = snd_usb_hw_free, |
---|
1963 | | - .prepare = snd_usb_pcm_prepare, |
---|
1964 | | - .trigger = snd_usb_substream_playback_trigger, |
---|
1965 | | - .pointer = snd_usb_pcm_pointer, |
---|
1966 | | - .page = snd_pcm_sgbuf_ops_page, |
---|
1967 | | -}; |
---|
1968 | | - |
---|
1969 | | -static const struct snd_pcm_ops snd_usb_capture_dev_ops = { |
---|
1970 | | - .open = snd_usb_pcm_open, |
---|
1971 | | - .close = snd_usb_pcm_close, |
---|
1972 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1973 | | - .hw_params = snd_usb_hw_params, |
---|
1974 | | - .hw_free = snd_usb_hw_free, |
---|
1975 | | - .prepare = snd_usb_pcm_prepare, |
---|
1976 | | - .trigger = snd_usb_substream_capture_trigger, |
---|
1977 | | - .pointer = snd_usb_pcm_pointer, |
---|
1978 | | - .page = snd_pcm_sgbuf_ops_page, |
---|
1979 | 2034 | }; |
---|
1980 | 2035 | |
---|
1981 | 2036 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) |
---|
1982 | 2037 | { |
---|
1983 | 2038 | const struct snd_pcm_ops *ops; |
---|
1984 | 2039 | |
---|
1985 | | - if (snd_usb_use_vmalloc) |
---|
1986 | | - ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? |
---|
| 2040 | + ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? |
---|
1987 | 2041 | &snd_usb_playback_ops : &snd_usb_capture_ops; |
---|
1988 | | - else |
---|
1989 | | - ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? |
---|
1990 | | - &snd_usb_playback_dev_ops : &snd_usb_capture_dev_ops; |
---|
1991 | 2042 | snd_pcm_set_ops(pcm, stream, ops); |
---|
1992 | 2043 | } |
---|
1993 | 2044 | |
---|
.. | .. |
---|
1997 | 2048 | struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; |
---|
1998 | 2049 | struct device *dev = subs->dev->bus->sysdev; |
---|
1999 | 2050 | |
---|
2000 | | - if (!snd_usb_use_vmalloc) |
---|
2001 | | - snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG, |
---|
2002 | | - dev, 64*1024, 512*1024); |
---|
| 2051 | + if (snd_usb_use_vmalloc) |
---|
| 2052 | + snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC, |
---|
| 2053 | + NULL, 0, 0); |
---|
| 2054 | + else |
---|
| 2055 | + snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_DEV_SG, |
---|
| 2056 | + dev, 64*1024, 512*1024); |
---|
2003 | 2057 | } |
---|