1*9b2bb4f2STakashi Sakamoto /* 2*9b2bb4f2STakashi Sakamoto * motu-stream.c - a part of driver for MOTU FireWire series 3*9b2bb4f2STakashi Sakamoto * 4*9b2bb4f2STakashi Sakamoto * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp> 5*9b2bb4f2STakashi Sakamoto * 6*9b2bb4f2STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 7*9b2bb4f2STakashi Sakamoto */ 8*9b2bb4f2STakashi Sakamoto 9*9b2bb4f2STakashi Sakamoto #include "motu.h" 10*9b2bb4f2STakashi Sakamoto 11*9b2bb4f2STakashi Sakamoto #define CALLBACK_TIMEOUT 200 12*9b2bb4f2STakashi Sakamoto 13*9b2bb4f2STakashi Sakamoto #define ISOC_COMM_CONTROL_OFFSET 0x0b00 14*9b2bb4f2STakashi Sakamoto #define ISOC_COMM_CONTROL_MASK 0xffff0000 15*9b2bb4f2STakashi Sakamoto #define CHANGE_RX_ISOC_COMM_STATE 0x80000000 16*9b2bb4f2STakashi Sakamoto #define RX_ISOC_COMM_IS_ACTIVATED 0x40000000 17*9b2bb4f2STakashi Sakamoto #define RX_ISOC_COMM_CHANNEL_MASK 0x3f000000 18*9b2bb4f2STakashi Sakamoto #define RX_ISOC_COMM_CHANNEL_SHIFT 24 19*9b2bb4f2STakashi Sakamoto #define CHANGE_TX_ISOC_COMM_STATE 0x00800000 20*9b2bb4f2STakashi Sakamoto #define TX_ISOC_COMM_IS_ACTIVATED 0x00400000 21*9b2bb4f2STakashi Sakamoto #define TX_ISOC_COMM_CHANNEL_MASK 0x003f0000 22*9b2bb4f2STakashi Sakamoto #define TX_ISOC_COMM_CHANNEL_SHIFT 16 23*9b2bb4f2STakashi Sakamoto 24*9b2bb4f2STakashi Sakamoto #define PACKET_FORMAT_OFFSET 0x0b10 25*9b2bb4f2STakashi Sakamoto #define TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080 26*9b2bb4f2STakashi Sakamoto #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040 27*9b2bb4f2STakashi Sakamoto #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f 28*9b2bb4f2STakashi Sakamoto 29*9b2bb4f2STakashi Sakamoto static int start_both_streams(struct snd_motu *motu, unsigned int rate) 30*9b2bb4f2STakashi Sakamoto { 31*9b2bb4f2STakashi Sakamoto __be32 reg; 32*9b2bb4f2STakashi Sakamoto u32 data; 33*9b2bb4f2STakashi Sakamoto int err; 34*9b2bb4f2STakashi Sakamoto 35*9b2bb4f2STakashi Sakamoto /* Set packet formation to our packet streaming engine. */ 36*9b2bb4f2STakashi Sakamoto err = amdtp_motu_set_parameters(&motu->rx_stream, rate, 37*9b2bb4f2STakashi Sakamoto &motu->rx_packet_formats); 38*9b2bb4f2STakashi Sakamoto if (err < 0) 39*9b2bb4f2STakashi Sakamoto return err; 40*9b2bb4f2STakashi Sakamoto 41*9b2bb4f2STakashi Sakamoto err = amdtp_motu_set_parameters(&motu->tx_stream, rate, 42*9b2bb4f2STakashi Sakamoto &motu->tx_packet_formats); 43*9b2bb4f2STakashi Sakamoto if (err < 0) 44*9b2bb4f2STakashi Sakamoto return err; 45*9b2bb4f2STakashi Sakamoto 46*9b2bb4f2STakashi Sakamoto 47*9b2bb4f2STakashi Sakamoto /* Get isochronous resources on the bus. */ 48*9b2bb4f2STakashi Sakamoto err = fw_iso_resources_allocate(&motu->rx_resources, 49*9b2bb4f2STakashi Sakamoto amdtp_stream_get_max_payload(&motu->rx_stream), 50*9b2bb4f2STakashi Sakamoto fw_parent_device(motu->unit)->max_speed); 51*9b2bb4f2STakashi Sakamoto if (err < 0) 52*9b2bb4f2STakashi Sakamoto return err; 53*9b2bb4f2STakashi Sakamoto 54*9b2bb4f2STakashi Sakamoto err = fw_iso_resources_allocate(&motu->tx_resources, 55*9b2bb4f2STakashi Sakamoto amdtp_stream_get_max_payload(&motu->tx_stream), 56*9b2bb4f2STakashi Sakamoto fw_parent_device(motu->unit)->max_speed); 57*9b2bb4f2STakashi Sakamoto if (err < 0) 58*9b2bb4f2STakashi Sakamoto return err; 59*9b2bb4f2STakashi Sakamoto 60*9b2bb4f2STakashi Sakamoto /* Configure the unit to start isochronous communication. */ 61*9b2bb4f2STakashi Sakamoto err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, 62*9b2bb4f2STakashi Sakamoto sizeof(reg)); 63*9b2bb4f2STakashi Sakamoto if (err < 0) 64*9b2bb4f2STakashi Sakamoto return err; 65*9b2bb4f2STakashi Sakamoto data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK; 66*9b2bb4f2STakashi Sakamoto 67*9b2bb4f2STakashi Sakamoto data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED | 68*9b2bb4f2STakashi Sakamoto (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) | 69*9b2bb4f2STakashi Sakamoto CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED | 70*9b2bb4f2STakashi Sakamoto (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT); 71*9b2bb4f2STakashi Sakamoto 72*9b2bb4f2STakashi Sakamoto reg = cpu_to_be32(data); 73*9b2bb4f2STakashi Sakamoto return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®, 74*9b2bb4f2STakashi Sakamoto sizeof(reg)); 75*9b2bb4f2STakashi Sakamoto } 76*9b2bb4f2STakashi Sakamoto 77*9b2bb4f2STakashi Sakamoto static void stop_both_streams(struct snd_motu *motu) 78*9b2bb4f2STakashi Sakamoto { 79*9b2bb4f2STakashi Sakamoto __be32 reg; 80*9b2bb4f2STakashi Sakamoto u32 data; 81*9b2bb4f2STakashi Sakamoto int err; 82*9b2bb4f2STakashi Sakamoto 83*9b2bb4f2STakashi Sakamoto err = motu->spec->protocol->switch_fetching_mode(motu, false); 84*9b2bb4f2STakashi Sakamoto if (err < 0) 85*9b2bb4f2STakashi Sakamoto return; 86*9b2bb4f2STakashi Sakamoto 87*9b2bb4f2STakashi Sakamoto err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, 88*9b2bb4f2STakashi Sakamoto sizeof(reg)); 89*9b2bb4f2STakashi Sakamoto if (err < 0) 90*9b2bb4f2STakashi Sakamoto return; 91*9b2bb4f2STakashi Sakamoto data = be32_to_cpu(reg); 92*9b2bb4f2STakashi Sakamoto 93*9b2bb4f2STakashi Sakamoto data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED); 94*9b2bb4f2STakashi Sakamoto data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE; 95*9b2bb4f2STakashi Sakamoto 96*9b2bb4f2STakashi Sakamoto reg = cpu_to_be32(data); 97*9b2bb4f2STakashi Sakamoto snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, ®, 98*9b2bb4f2STakashi Sakamoto sizeof(reg)); 99*9b2bb4f2STakashi Sakamoto 100*9b2bb4f2STakashi Sakamoto fw_iso_resources_free(&motu->tx_resources); 101*9b2bb4f2STakashi Sakamoto fw_iso_resources_free(&motu->rx_resources); 102*9b2bb4f2STakashi Sakamoto } 103*9b2bb4f2STakashi Sakamoto 104*9b2bb4f2STakashi Sakamoto static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) 105*9b2bb4f2STakashi Sakamoto { 106*9b2bb4f2STakashi Sakamoto struct fw_iso_resources *resources; 107*9b2bb4f2STakashi Sakamoto int err; 108*9b2bb4f2STakashi Sakamoto 109*9b2bb4f2STakashi Sakamoto if (stream == &motu->rx_stream) 110*9b2bb4f2STakashi Sakamoto resources = &motu->rx_resources; 111*9b2bb4f2STakashi Sakamoto else 112*9b2bb4f2STakashi Sakamoto resources = &motu->tx_resources; 113*9b2bb4f2STakashi Sakamoto 114*9b2bb4f2STakashi Sakamoto err = amdtp_stream_start(stream, resources->channel, 115*9b2bb4f2STakashi Sakamoto fw_parent_device(motu->unit)->max_speed); 116*9b2bb4f2STakashi Sakamoto if (err < 0) 117*9b2bb4f2STakashi Sakamoto return err; 118*9b2bb4f2STakashi Sakamoto 119*9b2bb4f2STakashi Sakamoto if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { 120*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(stream); 121*9b2bb4f2STakashi Sakamoto fw_iso_resources_free(resources); 122*9b2bb4f2STakashi Sakamoto return -ETIMEDOUT; 123*9b2bb4f2STakashi Sakamoto } 124*9b2bb4f2STakashi Sakamoto 125*9b2bb4f2STakashi Sakamoto return 0; 126*9b2bb4f2STakashi Sakamoto } 127*9b2bb4f2STakashi Sakamoto 128*9b2bb4f2STakashi Sakamoto static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) 129*9b2bb4f2STakashi Sakamoto { 130*9b2bb4f2STakashi Sakamoto struct fw_iso_resources *resources; 131*9b2bb4f2STakashi Sakamoto 132*9b2bb4f2STakashi Sakamoto if (stream == &motu->rx_stream) 133*9b2bb4f2STakashi Sakamoto resources = &motu->rx_resources; 134*9b2bb4f2STakashi Sakamoto else 135*9b2bb4f2STakashi Sakamoto resources = &motu->tx_resources; 136*9b2bb4f2STakashi Sakamoto 137*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(stream); 138*9b2bb4f2STakashi Sakamoto fw_iso_resources_free(resources); 139*9b2bb4f2STakashi Sakamoto } 140*9b2bb4f2STakashi Sakamoto 141*9b2bb4f2STakashi Sakamoto static int ensure_packet_formats(struct snd_motu *motu) 142*9b2bb4f2STakashi Sakamoto { 143*9b2bb4f2STakashi Sakamoto __be32 reg; 144*9b2bb4f2STakashi Sakamoto u32 data; 145*9b2bb4f2STakashi Sakamoto int err; 146*9b2bb4f2STakashi Sakamoto 147*9b2bb4f2STakashi Sakamoto err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, ®, 148*9b2bb4f2STakashi Sakamoto sizeof(reg)); 149*9b2bb4f2STakashi Sakamoto if (err < 0) 150*9b2bb4f2STakashi Sakamoto return err; 151*9b2bb4f2STakashi Sakamoto data = be32_to_cpu(reg); 152*9b2bb4f2STakashi Sakamoto 153*9b2bb4f2STakashi Sakamoto data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS | 154*9b2bb4f2STakashi Sakamoto RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS| 155*9b2bb4f2STakashi Sakamoto TX_PACKET_TRANSMISSION_SPEED_MASK); 156*9b2bb4f2STakashi Sakamoto if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0) 157*9b2bb4f2STakashi Sakamoto data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; 158*9b2bb4f2STakashi Sakamoto if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0) 159*9b2bb4f2STakashi Sakamoto data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS; 160*9b2bb4f2STakashi Sakamoto data |= fw_parent_device(motu->unit)->max_speed; 161*9b2bb4f2STakashi Sakamoto 162*9b2bb4f2STakashi Sakamoto reg = cpu_to_be32(data); 163*9b2bb4f2STakashi Sakamoto return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, ®, 164*9b2bb4f2STakashi Sakamoto sizeof(reg)); 165*9b2bb4f2STakashi Sakamoto } 166*9b2bb4f2STakashi Sakamoto 167*9b2bb4f2STakashi Sakamoto int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) 168*9b2bb4f2STakashi Sakamoto { 169*9b2bb4f2STakashi Sakamoto const struct snd_motu_protocol *protocol = motu->spec->protocol; 170*9b2bb4f2STakashi Sakamoto unsigned int curr_rate; 171*9b2bb4f2STakashi Sakamoto int err = 0; 172*9b2bb4f2STakashi Sakamoto 173*9b2bb4f2STakashi Sakamoto if (motu->capture_substreams == 0 && motu->playback_substreams == 0) 174*9b2bb4f2STakashi Sakamoto return 0; 175*9b2bb4f2STakashi Sakamoto 176*9b2bb4f2STakashi Sakamoto /* Some packet queueing errors. */ 177*9b2bb4f2STakashi Sakamoto if (amdtp_streaming_error(&motu->rx_stream) || 178*9b2bb4f2STakashi Sakamoto amdtp_streaming_error(&motu->tx_stream)) { 179*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(&motu->rx_stream); 180*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(&motu->tx_stream); 181*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 182*9b2bb4f2STakashi Sakamoto } 183*9b2bb4f2STakashi Sakamoto 184*9b2bb4f2STakashi Sakamoto err = protocol->cache_packet_formats(motu); 185*9b2bb4f2STakashi Sakamoto if (err < 0) 186*9b2bb4f2STakashi Sakamoto return err; 187*9b2bb4f2STakashi Sakamoto 188*9b2bb4f2STakashi Sakamoto /* Stop stream if rate is different. */ 189*9b2bb4f2STakashi Sakamoto err = protocol->get_clock_rate(motu, &curr_rate); 190*9b2bb4f2STakashi Sakamoto if (err < 0) { 191*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 192*9b2bb4f2STakashi Sakamoto "fail to get sampling rate: %d\n", err); 193*9b2bb4f2STakashi Sakamoto return err; 194*9b2bb4f2STakashi Sakamoto } 195*9b2bb4f2STakashi Sakamoto if (rate == 0) 196*9b2bb4f2STakashi Sakamoto rate = curr_rate; 197*9b2bb4f2STakashi Sakamoto if (rate != curr_rate) { 198*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(&motu->rx_stream); 199*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(&motu->tx_stream); 200*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 201*9b2bb4f2STakashi Sakamoto } 202*9b2bb4f2STakashi Sakamoto 203*9b2bb4f2STakashi Sakamoto if (!amdtp_stream_running(&motu->rx_stream)) { 204*9b2bb4f2STakashi Sakamoto err = protocol->set_clock_rate(motu, rate); 205*9b2bb4f2STakashi Sakamoto if (err < 0) { 206*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 207*9b2bb4f2STakashi Sakamoto "fail to set sampling rate: %d\n", err); 208*9b2bb4f2STakashi Sakamoto return err; 209*9b2bb4f2STakashi Sakamoto } 210*9b2bb4f2STakashi Sakamoto 211*9b2bb4f2STakashi Sakamoto err = ensure_packet_formats(motu); 212*9b2bb4f2STakashi Sakamoto if (err < 0) 213*9b2bb4f2STakashi Sakamoto return err; 214*9b2bb4f2STakashi Sakamoto 215*9b2bb4f2STakashi Sakamoto err = start_both_streams(motu, rate); 216*9b2bb4f2STakashi Sakamoto if (err < 0) { 217*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 218*9b2bb4f2STakashi Sakamoto "fail to start isochronous comm: %d\n", err); 219*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 220*9b2bb4f2STakashi Sakamoto return err; 221*9b2bb4f2STakashi Sakamoto } 222*9b2bb4f2STakashi Sakamoto 223*9b2bb4f2STakashi Sakamoto err = start_isoc_ctx(motu, &motu->rx_stream); 224*9b2bb4f2STakashi Sakamoto if (err < 0) { 225*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 226*9b2bb4f2STakashi Sakamoto "fail to start IT context: %d\n", err); 227*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 228*9b2bb4f2STakashi Sakamoto return err; 229*9b2bb4f2STakashi Sakamoto } 230*9b2bb4f2STakashi Sakamoto 231*9b2bb4f2STakashi Sakamoto err = protocol->switch_fetching_mode(motu, true); 232*9b2bb4f2STakashi Sakamoto if (err < 0) { 233*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 234*9b2bb4f2STakashi Sakamoto "fail to enable frame fetching: %d\n", err); 235*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 236*9b2bb4f2STakashi Sakamoto return err; 237*9b2bb4f2STakashi Sakamoto } 238*9b2bb4f2STakashi Sakamoto } 239*9b2bb4f2STakashi Sakamoto 240*9b2bb4f2STakashi Sakamoto if (!amdtp_stream_running(&motu->tx_stream) && 241*9b2bb4f2STakashi Sakamoto motu->capture_substreams > 0) { 242*9b2bb4f2STakashi Sakamoto err = start_isoc_ctx(motu, &motu->tx_stream); 243*9b2bb4f2STakashi Sakamoto if (err < 0) { 244*9b2bb4f2STakashi Sakamoto dev_err(&motu->unit->device, 245*9b2bb4f2STakashi Sakamoto "fail to start IR context: %d", err); 246*9b2bb4f2STakashi Sakamoto amdtp_stream_stop(&motu->rx_stream); 247*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 248*9b2bb4f2STakashi Sakamoto return err; 249*9b2bb4f2STakashi Sakamoto } 250*9b2bb4f2STakashi Sakamoto } 251*9b2bb4f2STakashi Sakamoto 252*9b2bb4f2STakashi Sakamoto return 0; 253*9b2bb4f2STakashi Sakamoto } 254*9b2bb4f2STakashi Sakamoto 255*9b2bb4f2STakashi Sakamoto void snd_motu_stream_stop_duplex(struct snd_motu *motu) 256*9b2bb4f2STakashi Sakamoto { 257*9b2bb4f2STakashi Sakamoto if (motu->capture_substreams == 0) { 258*9b2bb4f2STakashi Sakamoto if (amdtp_stream_running(&motu->tx_stream)) 259*9b2bb4f2STakashi Sakamoto stop_isoc_ctx(motu, &motu->tx_stream); 260*9b2bb4f2STakashi Sakamoto 261*9b2bb4f2STakashi Sakamoto if (motu->playback_substreams == 0) { 262*9b2bb4f2STakashi Sakamoto if (amdtp_stream_running(&motu->rx_stream)) 263*9b2bb4f2STakashi Sakamoto stop_isoc_ctx(motu, &motu->rx_stream); 264*9b2bb4f2STakashi Sakamoto stop_both_streams(motu); 265*9b2bb4f2STakashi Sakamoto } 266*9b2bb4f2STakashi Sakamoto } 267*9b2bb4f2STakashi Sakamoto } 268*9b2bb4f2STakashi Sakamoto 269*9b2bb4f2STakashi Sakamoto static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) 270*9b2bb4f2STakashi Sakamoto { 271*9b2bb4f2STakashi Sakamoto int err; 272*9b2bb4f2STakashi Sakamoto struct amdtp_stream *stream; 273*9b2bb4f2STakashi Sakamoto struct fw_iso_resources *resources; 274*9b2bb4f2STakashi Sakamoto 275*9b2bb4f2STakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 276*9b2bb4f2STakashi Sakamoto stream = &motu->tx_stream; 277*9b2bb4f2STakashi Sakamoto resources = &motu->tx_resources; 278*9b2bb4f2STakashi Sakamoto } else { 279*9b2bb4f2STakashi Sakamoto stream = &motu->rx_stream; 280*9b2bb4f2STakashi Sakamoto resources = &motu->rx_resources; 281*9b2bb4f2STakashi Sakamoto } 282*9b2bb4f2STakashi Sakamoto 283*9b2bb4f2STakashi Sakamoto err = fw_iso_resources_init(resources, motu->unit); 284*9b2bb4f2STakashi Sakamoto if (err < 0) 285*9b2bb4f2STakashi Sakamoto return err; 286*9b2bb4f2STakashi Sakamoto 287*9b2bb4f2STakashi Sakamoto err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol); 288*9b2bb4f2STakashi Sakamoto if (err < 0) { 289*9b2bb4f2STakashi Sakamoto amdtp_stream_destroy(stream); 290*9b2bb4f2STakashi Sakamoto fw_iso_resources_destroy(resources); 291*9b2bb4f2STakashi Sakamoto } 292*9b2bb4f2STakashi Sakamoto 293*9b2bb4f2STakashi Sakamoto return err; 294*9b2bb4f2STakashi Sakamoto } 295*9b2bb4f2STakashi Sakamoto 296*9b2bb4f2STakashi Sakamoto static void destroy_stream(struct snd_motu *motu, 297*9b2bb4f2STakashi Sakamoto enum amdtp_stream_direction dir) 298*9b2bb4f2STakashi Sakamoto { 299*9b2bb4f2STakashi Sakamoto struct amdtp_stream *stream; 300*9b2bb4f2STakashi Sakamoto struct fw_iso_resources *resources; 301*9b2bb4f2STakashi Sakamoto 302*9b2bb4f2STakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 303*9b2bb4f2STakashi Sakamoto stream = &motu->tx_stream; 304*9b2bb4f2STakashi Sakamoto resources = &motu->tx_resources; 305*9b2bb4f2STakashi Sakamoto } else { 306*9b2bb4f2STakashi Sakamoto stream = &motu->rx_stream; 307*9b2bb4f2STakashi Sakamoto resources = &motu->rx_resources; 308*9b2bb4f2STakashi Sakamoto } 309*9b2bb4f2STakashi Sakamoto 310*9b2bb4f2STakashi Sakamoto amdtp_stream_destroy(stream); 311*9b2bb4f2STakashi Sakamoto fw_iso_resources_free(resources); 312*9b2bb4f2STakashi Sakamoto } 313*9b2bb4f2STakashi Sakamoto 314*9b2bb4f2STakashi Sakamoto int snd_motu_stream_init_duplex(struct snd_motu *motu) 315*9b2bb4f2STakashi Sakamoto { 316*9b2bb4f2STakashi Sakamoto int err; 317*9b2bb4f2STakashi Sakamoto 318*9b2bb4f2STakashi Sakamoto err = init_stream(motu, AMDTP_IN_STREAM); 319*9b2bb4f2STakashi Sakamoto if (err < 0) 320*9b2bb4f2STakashi Sakamoto return err; 321*9b2bb4f2STakashi Sakamoto 322*9b2bb4f2STakashi Sakamoto err = init_stream(motu, AMDTP_OUT_STREAM); 323*9b2bb4f2STakashi Sakamoto if (err < 0) 324*9b2bb4f2STakashi Sakamoto destroy_stream(motu, AMDTP_IN_STREAM); 325*9b2bb4f2STakashi Sakamoto 326*9b2bb4f2STakashi Sakamoto return err; 327*9b2bb4f2STakashi Sakamoto } 328*9b2bb4f2STakashi Sakamoto 329*9b2bb4f2STakashi Sakamoto /* 330*9b2bb4f2STakashi Sakamoto * This function should be called before starting streams or after stopping 331*9b2bb4f2STakashi Sakamoto * streams. 332*9b2bb4f2STakashi Sakamoto */ 333*9b2bb4f2STakashi Sakamoto void snd_motu_stream_destroy_duplex(struct snd_motu *motu) 334*9b2bb4f2STakashi Sakamoto { 335*9b2bb4f2STakashi Sakamoto destroy_stream(motu, AMDTP_IN_STREAM); 336*9b2bb4f2STakashi Sakamoto destroy_stream(motu, AMDTP_OUT_STREAM); 337*9b2bb4f2STakashi Sakamoto 338*9b2bb4f2STakashi Sakamoto motu->playback_substreams = 0; 339*9b2bb4f2STakashi Sakamoto motu->capture_substreams = 0; 340*9b2bb4f2STakashi Sakamoto } 341