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.
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;
36 if ((motu
->spec
->flags
& SND_MOTU_SPEC_RX_MIDI_2ND_Q
) ||
37 (motu
->spec
->flags
& SND_MOTU_SPEC_RX_MIDI_3RD_Q
))
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
);
46 if ((motu
->spec
->flags
& SND_MOTU_SPEC_TX_MIDI_2ND_Q
) ||
47 (motu
->spec
->flags
& SND_MOTU_SPEC_TX_MIDI_3RD_Q
))
52 err
= amdtp_motu_set_parameters(&motu
->tx_stream
, rate
, midi_ports
,
53 &motu
->tx_packet_formats
);
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
);
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
);
70 /* Configure the unit to start isochronous communication. */
71 err
= snd_motu_transaction_read(motu
, ISOC_COMM_CONTROL_OFFSET
, ®
,
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
, ®
,
87 static void stop_both_streams(struct snd_motu
*motu
)
93 err
= motu
->spec
->protocol
->switch_fetching_mode(motu
, false);
97 err
= snd_motu_transaction_read(motu
, ISOC_COMM_CONTROL_OFFSET
, ®
,
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
, ®
,
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
;
119 if (stream
== &motu
->rx_stream
)
120 resources
= &motu
->rx_resources
;
122 resources
= &motu
->tx_resources
;
124 err
= amdtp_stream_start(stream
, resources
->channel
,
125 fw_parent_device(motu
->unit
)->max_speed
);
129 if (!amdtp_stream_wait_callback(stream
, CALLBACK_TIMEOUT
)) {
130 amdtp_stream_stop(stream
);
131 fw_iso_resources_free(resources
);
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
;
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
)
155 err
= motu
->spec
->protocol
->cache_packet_formats(motu
);
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;
178 static int ensure_packet_formats(struct snd_motu
*motu
)
184 err
= snd_motu_transaction_read(motu
, PACKET_FORMAT_OFFSET
, ®
,
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
, ®
,
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
;
210 if (motu
->capture_substreams
== 0 && motu
->playback_substreams
== 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
);
225 /* Stop stream if rate is different. */
226 err
= protocol
->get_clock_rate(motu
, &curr_rate
);
228 dev_err(&motu
->unit
->device
,
229 "fail to get sampling rate: %d\n", err
);
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
);
243 dev_err(&motu
->unit
->device
,
244 "fail to set sampling rate: %d\n", err
);
248 err
= ensure_packet_formats(motu
);
252 err
= start_both_streams(motu
, rate
);
254 dev_err(&motu
->unit
->device
,
255 "fail to start isochronous comm: %d\n", err
);
259 err
= start_isoc_ctx(motu
, &motu
->rx_stream
);
261 dev_err(&motu
->unit
->device
,
262 "fail to start IT context: %d\n", err
);
266 err
= protocol
->switch_fetching_mode(motu
, true);
268 dev_err(&motu
->unit
->device
,
269 "fail to enable frame fetching: %d\n", err
);
274 if (!amdtp_stream_running(&motu
->tx_stream
) &&
275 motu
->capture_substreams
> 0) {
276 err
= start_isoc_ctx(motu
, &motu
->tx_stream
);
278 dev_err(&motu
->unit
->device
,
279 "fail to start IR context: %d", err
);
280 amdtp_stream_stop(&motu
->rx_stream
);
288 stop_both_streams(motu
);
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
)
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
;
316 stream
= &motu
->rx_stream
;
317 resources
= &motu
->rx_resources
;
320 err
= fw_iso_resources_init(resources
, motu
->unit
);
324 err
= amdtp_motu_init(stream
, motu
->unit
, dir
, motu
->spec
->protocol
);
326 amdtp_stream_destroy(stream
);
327 fw_iso_resources_destroy(resources
);
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
;
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
)
355 err
= init_stream(motu
, AMDTP_IN_STREAM
);
359 err
= init_stream(motu
, AMDTP_OUT_STREAM
);
361 destroy_stream(motu
, AMDTP_IN_STREAM
);
367 * This function should be called before starting streams or after stopping
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
)
389 spin_lock_irq(&motu
->lock
);
391 if (motu
->dev_lock_count
< 0) {
396 if (motu
->dev_lock_count
++ == 0)
397 motu_lock_changed(motu
);
400 spin_unlock_irq(&motu
->lock
);
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))
411 if (--motu
->dev_lock_count
== 0)
412 motu_lock_changed(motu
);
414 spin_unlock_irq(&motu
->lock
);