Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * motu-stream.c - a part of driver for MOTU FireWire series
0004  *
0005  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
0006  */
0007 
0008 #include "motu.h"
0009 
0010 #define READY_TIMEOUT_MS    200
0011 
0012 #define ISOC_COMM_CONTROL_OFFSET        0x0b00
0013 #define  ISOC_COMM_CONTROL_MASK         0xffff0000
0014 #define  CHANGE_RX_ISOC_COMM_STATE      0x80000000
0015 #define  RX_ISOC_COMM_IS_ACTIVATED      0x40000000
0016 #define  RX_ISOC_COMM_CHANNEL_MASK      0x3f000000
0017 #define  RX_ISOC_COMM_CHANNEL_SHIFT     24
0018 #define  CHANGE_TX_ISOC_COMM_STATE      0x00800000
0019 #define  TX_ISOC_COMM_IS_ACTIVATED      0x00400000
0020 #define  TX_ISOC_COMM_CHANNEL_MASK      0x003f0000
0021 #define  TX_ISOC_COMM_CHANNEL_SHIFT     16
0022 
0023 #define PACKET_FORMAT_OFFSET            0x0b10
0024 #define  TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080
0025 #define  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040
0026 #define  TX_PACKET_TRANSMISSION_SPEED_MASK  0x0000000f
0027 
0028 static int keep_resources(struct snd_motu *motu, unsigned int rate,
0029               struct amdtp_stream *stream)
0030 {
0031     struct fw_iso_resources *resources;
0032     struct snd_motu_packet_format *packet_format;
0033     unsigned int midi_ports = 0;
0034     int err;
0035 
0036     if (stream == &motu->rx_stream) {
0037         resources = &motu->rx_resources;
0038         packet_format = &motu->rx_packet_formats;
0039 
0040         if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
0041             (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
0042             midi_ports = 1;
0043     } else {
0044         resources = &motu->tx_resources;
0045         packet_format = &motu->tx_packet_formats;
0046 
0047         if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
0048             (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
0049             midi_ports = 1;
0050     }
0051 
0052     err = amdtp_motu_set_parameters(stream, rate, midi_ports,
0053                     packet_format);
0054     if (err < 0)
0055         return err;
0056 
0057     return fw_iso_resources_allocate(resources,
0058                 amdtp_stream_get_max_payload(stream),
0059                 fw_parent_device(motu->unit)->max_speed);
0060 }
0061 
0062 static int begin_session(struct snd_motu *motu)
0063 {
0064     __be32 reg;
0065     u32 data;
0066     int err;
0067 
0068     // Configure the unit to start isochronous communication.
0069     err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
0070                     sizeof(reg));
0071     if (err < 0)
0072         return err;
0073     data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
0074 
0075     data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
0076         (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
0077         CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
0078         (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
0079 
0080     reg = cpu_to_be32(data);
0081     return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
0082                       sizeof(reg));
0083 }
0084 
0085 static void finish_session(struct snd_motu *motu)
0086 {
0087     __be32 reg;
0088     u32 data;
0089     int err;
0090 
0091     err = snd_motu_protocol_switch_fetching_mode(motu, false);
0092     if (err < 0)
0093         return;
0094 
0095     err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
0096                     sizeof(reg));
0097     if (err < 0)
0098         return;
0099     data = be32_to_cpu(reg);
0100 
0101     data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
0102     data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
0103 
0104     reg = cpu_to_be32(data);
0105     snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
0106                    sizeof(reg));
0107 }
0108 
0109 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
0110 {
0111     int err;
0112 
0113     err = snd_motu_protocol_cache_packet_formats(motu);
0114     if (err < 0)
0115         return err;
0116 
0117     if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
0118         motu->tx_packet_formats.midi_flag_offset = 4;
0119         motu->tx_packet_formats.midi_byte_offset = 6;
0120     } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
0121         motu->tx_packet_formats.midi_flag_offset = 8;
0122         motu->tx_packet_formats.midi_byte_offset = 7;
0123     }
0124 
0125     if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
0126         motu->rx_packet_formats.midi_flag_offset = 4;
0127         motu->rx_packet_formats.midi_byte_offset = 6;
0128     } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
0129         motu->rx_packet_formats.midi_flag_offset = 8;
0130         motu->rx_packet_formats.midi_byte_offset = 7;
0131     }
0132 
0133     return 0;
0134 }
0135 
0136 int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
0137                    unsigned int frames_per_period,
0138                    unsigned int frames_per_buffer)
0139 {
0140     unsigned int curr_rate;
0141     int err;
0142 
0143     err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
0144     if (err < 0)
0145         return err;
0146     if (rate == 0)
0147         rate = curr_rate;
0148 
0149     if (motu->substreams_counter == 0 || curr_rate != rate) {
0150         amdtp_domain_stop(&motu->domain);
0151         finish_session(motu);
0152 
0153         fw_iso_resources_free(&motu->tx_resources);
0154         fw_iso_resources_free(&motu->rx_resources);
0155 
0156         kfree(motu->cache.event_offsets);
0157         motu->cache.event_offsets = NULL;
0158 
0159         err = snd_motu_protocol_set_clock_rate(motu, rate);
0160         if (err < 0) {
0161             dev_err(&motu->unit->device,
0162                 "fail to set sampling rate: %d\n", err);
0163             return err;
0164         }
0165 
0166         err = snd_motu_stream_cache_packet_formats(motu);
0167         if (err < 0)
0168             return err;
0169 
0170         err = keep_resources(motu, rate, &motu->tx_stream);
0171         if (err < 0)
0172             return err;
0173 
0174         err = keep_resources(motu, rate, &motu->rx_stream);
0175         if (err < 0) {
0176             fw_iso_resources_free(&motu->tx_resources);
0177             return err;
0178         }
0179 
0180         err = amdtp_domain_set_events_per_period(&motu->domain,
0181                     frames_per_period, frames_per_buffer);
0182         if (err < 0) {
0183             fw_iso_resources_free(&motu->tx_resources);
0184             fw_iso_resources_free(&motu->rx_resources);
0185             return err;
0186         }
0187 
0188         motu->cache.size = motu->tx_stream.syt_interval * frames_per_buffer;
0189         motu->cache.event_offsets = kcalloc(motu->cache.size, sizeof(*motu->cache.event_offsets),
0190                           GFP_KERNEL);
0191         if (!motu->cache.event_offsets) {
0192             fw_iso_resources_free(&motu->tx_resources);
0193             fw_iso_resources_free(&motu->rx_resources);
0194             return -ENOMEM;
0195         }
0196     }
0197 
0198     return 0;
0199 }
0200 
0201 static int ensure_packet_formats(struct snd_motu *motu)
0202 {
0203     __be32 reg;
0204     u32 data;
0205     int err;
0206 
0207     err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
0208                     sizeof(reg));
0209     if (err < 0)
0210         return err;
0211     data = be32_to_cpu(reg);
0212 
0213     data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
0214           RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
0215           TX_PACKET_TRANSMISSION_SPEED_MASK);
0216     if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
0217         data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
0218     if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
0219         data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
0220     data |= fw_parent_device(motu->unit)->max_speed;
0221 
0222     reg = cpu_to_be32(data);
0223     return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
0224                       sizeof(reg));
0225 }
0226 
0227 int snd_motu_stream_start_duplex(struct snd_motu *motu)
0228 {
0229     unsigned int generation = motu->rx_resources.generation;
0230     int err = 0;
0231 
0232     if (motu->substreams_counter == 0)
0233         return 0;
0234 
0235     if (amdtp_streaming_error(&motu->rx_stream) ||
0236         amdtp_streaming_error(&motu->tx_stream)) {
0237         amdtp_domain_stop(&motu->domain);
0238         finish_session(motu);
0239     }
0240 
0241     if (generation != fw_parent_device(motu->unit)->card->generation) {
0242         err = fw_iso_resources_update(&motu->rx_resources);
0243         if (err < 0)
0244             return err;
0245 
0246         err = fw_iso_resources_update(&motu->tx_resources);
0247         if (err < 0)
0248             return err;
0249     }
0250 
0251     if (!amdtp_stream_running(&motu->rx_stream)) {
0252         int spd = fw_parent_device(motu->unit)->max_speed;
0253 
0254         err = ensure_packet_formats(motu);
0255         if (err < 0)
0256             return err;
0257 
0258         if (motu->spec->flags & SND_MOTU_SPEC_REGISTER_DSP) {
0259             err = snd_motu_register_dsp_message_parser_init(motu);
0260             if (err < 0)
0261                 return err;
0262         } else if (motu->spec->flags & SND_MOTU_SPEC_COMMAND_DSP) {
0263             err = snd_motu_command_dsp_message_parser_init(motu, motu->tx_stream.sfc);
0264             if (err < 0)
0265                 return err;
0266         }
0267 
0268         err = begin_session(motu);
0269         if (err < 0) {
0270             dev_err(&motu->unit->device,
0271                 "fail to start isochronous comm: %d\n", err);
0272             goto stop_streams;
0273         }
0274 
0275         err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
0276                           motu->tx_resources.channel, spd);
0277         if (err < 0)
0278             goto stop_streams;
0279 
0280         err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream,
0281                           motu->rx_resources.channel, spd);
0282         if (err < 0)
0283             goto stop_streams;
0284 
0285         motu->cache.tail = 0;
0286         motu->cache.tx_cycle_count = UINT_MAX;
0287         motu->cache.head = 0;
0288         motu->cache.rx_cycle_count = UINT_MAX;
0289 
0290         // NOTE: The device requires both of replay; the sequence of the number of data
0291         // blocks per packet, and the sequence of source packet header per data block as
0292         // presentation time.
0293         err = amdtp_domain_start(&motu->domain, 0, true, false);
0294         if (err < 0)
0295             goto stop_streams;
0296 
0297         if (!amdtp_domain_wait_ready(&motu->domain, READY_TIMEOUT_MS)) {
0298             err = -ETIMEDOUT;
0299             goto stop_streams;
0300         }
0301 
0302         err = snd_motu_protocol_switch_fetching_mode(motu, true);
0303         if (err < 0) {
0304             dev_err(&motu->unit->device,
0305                 "fail to enable frame fetching: %d\n", err);
0306             goto stop_streams;
0307         }
0308     }
0309 
0310     return 0;
0311 
0312 stop_streams:
0313     amdtp_domain_stop(&motu->domain);
0314     finish_session(motu);
0315     return err;
0316 }
0317 
0318 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
0319 {
0320     if (motu->substreams_counter == 0) {
0321         amdtp_domain_stop(&motu->domain);
0322         finish_session(motu);
0323 
0324         fw_iso_resources_free(&motu->tx_resources);
0325         fw_iso_resources_free(&motu->rx_resources);
0326 
0327         kfree(motu->cache.event_offsets);
0328         motu->cache.event_offsets = NULL;
0329     }
0330 }
0331 
0332 static int init_stream(struct snd_motu *motu, struct amdtp_stream *s)
0333 {
0334     struct fw_iso_resources *resources;
0335     enum amdtp_stream_direction dir;
0336     int err;
0337 
0338     if (s == &motu->tx_stream) {
0339         resources = &motu->tx_resources;
0340         dir = AMDTP_IN_STREAM;
0341     } else {
0342         resources = &motu->rx_resources;
0343         dir = AMDTP_OUT_STREAM;
0344     }
0345 
0346     err = fw_iso_resources_init(resources, motu->unit);
0347     if (err < 0)
0348         return err;
0349 
0350     err = amdtp_motu_init(s, motu->unit, dir, motu->spec, &motu->cache);
0351     if (err < 0)
0352         fw_iso_resources_destroy(resources);
0353 
0354     return err;
0355 }
0356 
0357 static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s)
0358 {
0359     amdtp_stream_destroy(s);
0360 
0361     if (s == &motu->tx_stream)
0362         fw_iso_resources_destroy(&motu->tx_resources);
0363     else
0364         fw_iso_resources_destroy(&motu->rx_resources);
0365 }
0366 
0367 int snd_motu_stream_init_duplex(struct snd_motu *motu)
0368 {
0369     int err;
0370 
0371     err = init_stream(motu, &motu->tx_stream);
0372     if (err < 0)
0373         return err;
0374 
0375     err = init_stream(motu, &motu->rx_stream);
0376     if (err < 0) {
0377         destroy_stream(motu, &motu->tx_stream);
0378         return err;
0379     }
0380 
0381     err = amdtp_domain_init(&motu->domain);
0382     if (err < 0) {
0383         destroy_stream(motu, &motu->tx_stream);
0384         destroy_stream(motu, &motu->rx_stream);
0385     }
0386 
0387     return err;
0388 }
0389 
0390 // This function should be called before starting streams or after stopping
0391 // streams.
0392 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
0393 {
0394     amdtp_domain_destroy(&motu->domain);
0395 
0396     destroy_stream(motu, &motu->rx_stream);
0397     destroy_stream(motu, &motu->tx_stream);
0398 
0399     motu->substreams_counter = 0;
0400 }
0401 
0402 static void motu_lock_changed(struct snd_motu *motu)
0403 {
0404     motu->dev_lock_changed = true;
0405     wake_up(&motu->hwdep_wait);
0406 }
0407 
0408 int snd_motu_stream_lock_try(struct snd_motu *motu)
0409 {
0410     int err;
0411 
0412     spin_lock_irq(&motu->lock);
0413 
0414     if (motu->dev_lock_count < 0) {
0415         err = -EBUSY;
0416         goto out;
0417     }
0418 
0419     if (motu->dev_lock_count++ == 0)
0420         motu_lock_changed(motu);
0421     err = 0;
0422 out:
0423     spin_unlock_irq(&motu->lock);
0424     return err;
0425 }
0426 
0427 void snd_motu_stream_lock_release(struct snd_motu *motu)
0428 {
0429     spin_lock_irq(&motu->lock);
0430 
0431     if (WARN_ON(motu->dev_lock_count <= 0))
0432         goto out;
0433 
0434     if (--motu->dev_lock_count == 0)
0435         motu_lock_changed(motu);
0436 out:
0437     spin_unlock_irq(&motu->lock);
0438 }