]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - sound/firewire/motu/motu-stream.c
perf test: Fix vmlinux failure on s390x part 2
[mirror_ubuntu-bionic-kernel.git] / sound / firewire / motu / motu-stream.c
1 /*
2 * motu-stream.c - a part of driver for MOTU FireWire series
3 *
4 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9 #include "motu.h"
10
11 #define CALLBACK_TIMEOUT 200
12
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
23
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
28
29 static int start_both_streams(struct snd_motu *motu, unsigned int rate)
30 {
31 unsigned int midi_ports = 0;
32 __be32 reg;
33 u32 data;
34 int err;
35
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;
39
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;
45
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;
51
52 err = amdtp_motu_set_parameters(&motu->tx_stream, rate, midi_ports,
53 &motu->tx_packet_formats);
54 if (err < 0)
55 return err;
56
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;
63
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;
69
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;
76
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);
81
82 reg = cpu_to_be32(data);
83 return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
84 sizeof(reg));
85 }
86
87 static void stop_both_streams(struct snd_motu *motu)
88 {
89 __be32 reg;
90 u32 data;
91 int err;
92
93 err = motu->spec->protocol->switch_fetching_mode(motu, false);
94 if (err < 0)
95 return;
96
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);
102
103 data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
104 data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
105
106 reg = cpu_to_be32(data);
107 snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
108 sizeof(reg));
109
110 fw_iso_resources_free(&motu->tx_resources);
111 fw_iso_resources_free(&motu->rx_resources);
112 }
113
114 static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
115 {
116 struct fw_iso_resources *resources;
117 int err;
118
119 if (stream == &motu->rx_stream)
120 resources = &motu->rx_resources;
121 else
122 resources = &motu->tx_resources;
123
124 err = amdtp_stream_start(stream, resources->channel,
125 fw_parent_device(motu->unit)->max_speed);
126 if (err < 0)
127 return err;
128
129 if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
130 amdtp_stream_stop(stream);
131 fw_iso_resources_free(resources);
132 return -ETIMEDOUT;
133 }
134
135 return 0;
136 }
137
138 static void stop_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
139 {
140 struct fw_iso_resources *resources;
141
142 if (stream == &motu->rx_stream)
143 resources = &motu->rx_resources;
144 else
145 resources = &motu->tx_resources;
146
147 amdtp_stream_stop(stream);
148 fw_iso_resources_free(resources);
149 }
150
151 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
152 {
153 int err;
154
155 err = motu->spec->protocol->cache_packet_formats(motu);
156 if (err < 0)
157 return err;
158
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;
165 }
166
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;
173 }
174
175 return 0;
176 }
177
178 static int ensure_packet_formats(struct snd_motu *motu)
179 {
180 __be32 reg;
181 u32 data;
182 int err;
183
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);
189
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;
198
199 reg = cpu_to_be32(data);
200 return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
201 sizeof(reg));
202 }
203
204 int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate)
205 {
206 const struct snd_motu_protocol *protocol = motu->spec->protocol;
207 unsigned int curr_rate;
208 int err = 0;
209
210 if (motu->capture_substreams == 0 && motu->playback_substreams == 0)
211 return 0;
212
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);
219 }
220
221 err = snd_motu_stream_cache_packet_formats(motu);
222 if (err < 0)
223 return err;
224
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;
231 }
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);
238 }
239
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;
246 }
247
248 err = ensure_packet_formats(motu);
249 if (err < 0)
250 return err;
251
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 stop_both_streams(motu);
257 return err;
258 }
259
260 err = start_isoc_ctx(motu, &motu->rx_stream);
261 if (err < 0) {
262 dev_err(&motu->unit->device,
263 "fail to start IT context: %d\n", err);
264 stop_both_streams(motu);
265 return err;
266 }
267
268 err = protocol->switch_fetching_mode(motu, true);
269 if (err < 0) {
270 dev_err(&motu->unit->device,
271 "fail to enable frame fetching: %d\n", err);
272 stop_both_streams(motu);
273 return err;
274 }
275 }
276
277 if (!amdtp_stream_running(&motu->tx_stream) &&
278 motu->capture_substreams > 0) {
279 err = start_isoc_ctx(motu, &motu->tx_stream);
280 if (err < 0) {
281 dev_err(&motu->unit->device,
282 "fail to start IR context: %d", err);
283 amdtp_stream_stop(&motu->rx_stream);
284 stop_both_streams(motu);
285 return err;
286 }
287 }
288
289 return 0;
290 }
291
292 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
293 {
294 if (motu->capture_substreams == 0) {
295 if (amdtp_stream_running(&motu->tx_stream))
296 stop_isoc_ctx(motu, &motu->tx_stream);
297
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);
302 }
303 }
304 }
305
306 static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir)
307 {
308 int err;
309 struct amdtp_stream *stream;
310 struct fw_iso_resources *resources;
311
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;
318 }
319
320 err = fw_iso_resources_init(resources, motu->unit);
321 if (err < 0)
322 return err;
323
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);
328 }
329
330 return err;
331 }
332
333 static void destroy_stream(struct snd_motu *motu,
334 enum amdtp_stream_direction dir)
335 {
336 struct amdtp_stream *stream;
337 struct fw_iso_resources *resources;
338
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;
345 }
346
347 amdtp_stream_destroy(stream);
348 fw_iso_resources_free(resources);
349 }
350
351 int snd_motu_stream_init_duplex(struct snd_motu *motu)
352 {
353 int err;
354
355 err = init_stream(motu, AMDTP_IN_STREAM);
356 if (err < 0)
357 return err;
358
359 err = init_stream(motu, AMDTP_OUT_STREAM);
360 if (err < 0)
361 destroy_stream(motu, AMDTP_IN_STREAM);
362
363 return err;
364 }
365
366 /*
367 * This function should be called before starting streams or after stopping
368 * streams.
369 */
370 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
371 {
372 destroy_stream(motu, AMDTP_IN_STREAM);
373 destroy_stream(motu, AMDTP_OUT_STREAM);
374
375 motu->playback_substreams = 0;
376 motu->capture_substreams = 0;
377 }
378
379 static void motu_lock_changed(struct snd_motu *motu)
380 {
381 motu->dev_lock_changed = true;
382 wake_up(&motu->hwdep_wait);
383 }
384
385 int snd_motu_stream_lock_try(struct snd_motu *motu)
386 {
387 int err;
388
389 spin_lock_irq(&motu->lock);
390
391 if (motu->dev_lock_count < 0) {
392 err = -EBUSY;
393 goto out;
394 }
395
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;
402 }
403
404 void snd_motu_stream_lock_release(struct snd_motu *motu)
405 {
406 spin_lock_irq(&motu->lock);
407
408 if (WARN_ON(motu->dev_lock_count <= 0))
409 goto out;
410
411 if (--motu->dev_lock_count == 0)
412 motu_lock_changed(motu);
413 out:
414 spin_unlock_irq(&motu->lock);
415 }