Linux 4.18.10
[linux/fpc-iii.git] / sound / firewire / motu / motu-stream.c
blob73e7a5e527fc02445cab88df91f81c4ceae883f2
1 /*
2 * motu-stream.c - a part of driver for MOTU FireWire series
4 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
9 #include "motu.h"
11 #define CALLBACK_TIMEOUT 200
13 #define ISOC_COMM_CONTROL_OFFSET 0x0b00
14 #define ISOC_COMM_CONTROL_MASK 0xffff0000
15 #define CHANGE_RX_ISOC_COMM_STATE 0x80000000
16 #define RX_ISOC_COMM_IS_ACTIVATED 0x40000000
17 #define RX_ISOC_COMM_CHANNEL_MASK 0x3f000000
18 #define RX_ISOC_COMM_CHANNEL_SHIFT 24
19 #define CHANGE_TX_ISOC_COMM_STATE 0x00800000
20 #define TX_ISOC_COMM_IS_ACTIVATED 0x00400000
21 #define TX_ISOC_COMM_CHANNEL_MASK 0x003f0000
22 #define TX_ISOC_COMM_CHANNEL_SHIFT 16
24 #define PACKET_FORMAT_OFFSET 0x0b10
25 #define TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000080
26 #define RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS 0x00000040
27 #define TX_PACKET_TRANSMISSION_SPEED_MASK 0x0000000f
29 static int start_both_streams(struct snd_motu *motu, unsigned int rate)
31 unsigned int midi_ports = 0;
32 __be32 reg;
33 u32 data;
34 int err;
36 if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
37 (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
38 midi_ports = 1;
40 /* Set packet formation to our packet streaming engine. */
41 err = amdtp_motu_set_parameters(&motu->rx_stream, rate, midi_ports,
42 &motu->rx_packet_formats);
43 if (err < 0)
44 return err;
46 if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
47 (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
48 midi_ports = 1;
49 else
50 midi_ports = 0;
52 err = amdtp_motu_set_parameters(&motu->tx_stream, rate, midi_ports,
53 &motu->tx_packet_formats);
54 if (err < 0)
55 return err;
57 /* Get isochronous resources on the bus. */
58 err = fw_iso_resources_allocate(&motu->rx_resources,
59 amdtp_stream_get_max_payload(&motu->rx_stream),
60 fw_parent_device(motu->unit)->max_speed);
61 if (err < 0)
62 return err;
64 err = fw_iso_resources_allocate(&motu->tx_resources,
65 amdtp_stream_get_max_payload(&motu->tx_stream),
66 fw_parent_device(motu->unit)->max_speed);
67 if (err < 0)
68 return err;
70 /* Configure the unit to start isochronous communication. */
71 err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
72 sizeof(reg));
73 if (err < 0)
74 return err;
75 data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
77 data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
78 (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
79 CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
80 (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
82 reg = cpu_to_be32(data);
83 return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
84 sizeof(reg));
87 static void stop_both_streams(struct snd_motu *motu)
89 __be32 reg;
90 u32 data;
91 int err;
93 err = motu->spec->protocol->switch_fetching_mode(motu, false);
94 if (err < 0)
95 return;
97 err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
98 sizeof(reg));
99 if (err < 0)
100 return;
101 data = be32_to_cpu(reg);
103 data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
104 data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
106 reg = cpu_to_be32(data);
107 snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
108 sizeof(reg));
110 fw_iso_resources_free(&motu->tx_resources);
111 fw_iso_resources_free(&motu->rx_resources);
114 static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
116 struct fw_iso_resources *resources;
117 int err;
119 if (stream == &motu->rx_stream)
120 resources = &motu->rx_resources;
121 else
122 resources = &motu->tx_resources;
124 err = amdtp_stream_start(stream, resources->channel,
125 fw_parent_device(motu->unit)->max_speed);
126 if (err < 0)
127 return err;
129 if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
130 amdtp_stream_stop(stream);
131 fw_iso_resources_free(resources);
132 return -ETIMEDOUT;
135 return 0;
138 static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
140 struct fw_iso_resources *resources;
142 if (stream == &motu->rx_stream)
143 resources = &motu->rx_resources;
144 else
145 resources = &motu->tx_resources;
147 amdtp_stream_stop(stream);
148 fw_iso_resources_free(resources);
151 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
153 int err;
155 err = motu->spec->protocol->cache_packet_formats(motu);
156 if (err < 0)
157 return err;
159 if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
160 motu->tx_packet_formats.midi_flag_offset = 4;
161 motu->tx_packet_formats.midi_byte_offset = 6;
162 } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
163 motu->tx_packet_formats.midi_flag_offset = 8;
164 motu->tx_packet_formats.midi_byte_offset = 7;
167 if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
168 motu->rx_packet_formats.midi_flag_offset = 4;
169 motu->rx_packet_formats.midi_byte_offset = 6;
170 } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
171 motu->rx_packet_formats.midi_flag_offset = 8;
172 motu->rx_packet_formats.midi_byte_offset = 7;
175 return 0;
178 static int ensure_packet_formats(struct snd_motu *motu)
180 __be32 reg;
181 u32 data;
182 int err;
184 err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
185 sizeof(reg));
186 if (err < 0)
187 return err;
188 data = be32_to_cpu(reg);
190 data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
191 RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
192 TX_PACKET_TRANSMISSION_SPEED_MASK);
193 if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0)
194 data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
195 if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0)
196 data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
197 data |= fw_parent_device(motu->unit)->max_speed;
199 reg = cpu_to_be32(data);
200 return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
201 sizeof(reg));
204 int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate)
206 const struct snd_motu_protocol *protocol = motu->spec->protocol;
207 unsigned int curr_rate;
208 int err = 0;
210 if (motu->capture_substreams == 0 && motu->playback_substreams == 0)
211 return 0;
213 /* Some packet queueing errors. */
214 if (amdtp_streaming_error(&motu->rx_stream) ||
215 amdtp_streaming_error(&motu->tx_stream)) {
216 amdtp_stream_stop(&motu->rx_stream);
217 amdtp_stream_stop(&motu->tx_stream);
218 stop_both_streams(motu);
221 err = snd_motu_stream_cache_packet_formats(motu);
222 if (err < 0)
223 return err;
225 /* Stop stream if rate is different. */
226 err = protocol->get_clock_rate(motu, &curr_rate);
227 if (err < 0) {
228 dev_err(&motu->unit->device,
229 "fail to get sampling rate: %d\n", err);
230 return err;
232 if (rate == 0)
233 rate = curr_rate;
234 if (rate != curr_rate) {
235 amdtp_stream_stop(&motu->rx_stream);
236 amdtp_stream_stop(&motu->tx_stream);
237 stop_both_streams(motu);
240 if (!amdtp_stream_running(&motu->rx_stream)) {
241 err = protocol->set_clock_rate(motu, rate);
242 if (err < 0) {
243 dev_err(&motu->unit->device,
244 "fail to set sampling rate: %d\n", err);
245 return err;
248 err = ensure_packet_formats(motu);
249 if (err < 0)
250 return err;
252 err = start_both_streams(motu, rate);
253 if (err < 0) {
254 dev_err(&motu->unit->device,
255 "fail to start isochronous comm: %d\n", err);
256 goto stop_streams;
259 err = start_isoc_ctx(motu, &motu->rx_stream);
260 if (err < 0) {
261 dev_err(&motu->unit->device,
262 "fail to start IT context: %d\n", err);
263 goto stop_streams;
266 err = protocol->switch_fetching_mode(motu, true);
267 if (err < 0) {
268 dev_err(&motu->unit->device,
269 "fail to enable frame fetching: %d\n", err);
270 goto stop_streams;
274 if (!amdtp_stream_running(&motu->tx_stream) &&
275 motu->capture_substreams > 0) {
276 err = start_isoc_ctx(motu, &motu->tx_stream);
277 if (err < 0) {
278 dev_err(&motu->unit->device,
279 "fail to start IR context: %d", err);
280 amdtp_stream_stop(&motu->rx_stream);
281 goto stop_streams;
285 return 0;
287 stop_streams:
288 stop_both_streams(motu);
289 return err;
292 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
294 if (motu->capture_substreams == 0) {
295 if (amdtp_stream_running(&motu->tx_stream))
296 stop_isoc_ctx(motu, &motu->tx_stream);
298 if (motu->playback_substreams == 0) {
299 if (amdtp_stream_running(&motu->rx_stream))
300 stop_isoc_ctx(motu, &motu->rx_stream);
301 stop_both_streams(motu);
306 static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir)
308 int err;
309 struct amdtp_stream *stream;
310 struct fw_iso_resources *resources;
312 if (dir == AMDTP_IN_STREAM) {
313 stream = &motu->tx_stream;
314 resources = &motu->tx_resources;
315 } else {
316 stream = &motu->rx_stream;
317 resources = &motu->rx_resources;
320 err = fw_iso_resources_init(resources, motu->unit);
321 if (err < 0)
322 return err;
324 err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol);
325 if (err < 0) {
326 amdtp_stream_destroy(stream);
327 fw_iso_resources_destroy(resources);
330 return err;
333 static void destroy_stream(struct snd_motu *motu,
334 enum amdtp_stream_direction dir)
336 struct amdtp_stream *stream;
337 struct fw_iso_resources *resources;
339 if (dir == AMDTP_IN_STREAM) {
340 stream = &motu->tx_stream;
341 resources = &motu->tx_resources;
342 } else {
343 stream = &motu->rx_stream;
344 resources = &motu->rx_resources;
347 amdtp_stream_destroy(stream);
348 fw_iso_resources_free(resources);
351 int snd_motu_stream_init_duplex(struct snd_motu *motu)
353 int err;
355 err = init_stream(motu, AMDTP_IN_STREAM);
356 if (err < 0)
357 return err;
359 err = init_stream(motu, AMDTP_OUT_STREAM);
360 if (err < 0)
361 destroy_stream(motu, AMDTP_IN_STREAM);
363 return err;
367 * This function should be called before starting streams or after stopping
368 * streams.
370 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
372 destroy_stream(motu, AMDTP_IN_STREAM);
373 destroy_stream(motu, AMDTP_OUT_STREAM);
375 motu->playback_substreams = 0;
376 motu->capture_substreams = 0;
379 static void motu_lock_changed(struct snd_motu *motu)
381 motu->dev_lock_changed = true;
382 wake_up(&motu->hwdep_wait);
385 int snd_motu_stream_lock_try(struct snd_motu *motu)
387 int err;
389 spin_lock_irq(&motu->lock);
391 if (motu->dev_lock_count < 0) {
392 err = -EBUSY;
393 goto out;
396 if (motu->dev_lock_count++ == 0)
397 motu_lock_changed(motu);
398 err = 0;
399 out:
400 spin_unlock_irq(&motu->lock);
401 return err;
404 void snd_motu_stream_lock_release(struct snd_motu *motu)
406 spin_lock_irq(&motu->lock);
408 if (WARN_ON(motu->dev_lock_count <= 0))
409 goto out;
411 if (--motu->dev_lock_count == 0)
412 motu_lock_changed(motu);
413 out:
414 spin_unlock_irq(&motu->lock);