Merge branch 'for-linus' into for-next
[linux-2.6-block.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 keep_resources(struct snd_motu *motu, unsigned int rate,
30                           struct amdtp_stream *stream)
31 {
32         struct fw_iso_resources *resources;
33         struct snd_motu_packet_format *packet_format;
34         unsigned int midi_ports = 0;
35         int err;
36
37         if (stream == &motu->rx_stream) {
38                 resources = &motu->rx_resources;
39                 packet_format = &motu->rx_packet_formats;
40
41                 if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
42                     (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
43                         midi_ports = 1;
44         } else {
45                 resources = &motu->tx_resources;
46                 packet_format = &motu->tx_packet_formats;
47
48                 if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
49                     (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
50                         midi_ports = 1;
51         }
52
53         err = amdtp_motu_set_parameters(stream, rate, midi_ports,
54                                         packet_format);
55         if (err < 0)
56                 return err;
57
58         return fw_iso_resources_allocate(resources,
59                                 amdtp_stream_get_max_payload(stream),
60                                 fw_parent_device(motu->unit)->max_speed);
61 }
62
63 static int begin_session(struct snd_motu *motu)
64 {
65         __be32 reg;
66         u32 data;
67         int err;
68
69         // Configure the unit to start isochronous communication.
70         err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
71                                         sizeof(reg));
72         if (err < 0)
73                 return err;
74         data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
75
76         data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
77                 (motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
78                 CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
79                 (motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
80
81         reg = cpu_to_be32(data);
82         return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
83                                           sizeof(reg));
84 }
85
86 static void finish_session(struct snd_motu *motu)
87 {
88         __be32 reg;
89         u32 data;
90         int err;
91
92         err = motu->spec->protocol->switch_fetching_mode(motu, false);
93         if (err < 0)
94                 return;
95
96         amdtp_stream_stop(&motu->tx_stream);
97         amdtp_stream_stop(&motu->rx_stream);
98
99         err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
100                                         sizeof(reg));
101         if (err < 0)
102                 return;
103         data = be32_to_cpu(reg);
104
105         data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
106         data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
107
108         reg = cpu_to_be32(data);
109         snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
110                                    sizeof(reg));
111 }
112
113 static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
114 {
115         struct fw_iso_resources *resources;
116         int err;
117
118         if (stream == &motu->rx_stream)
119                 resources = &motu->rx_resources;
120         else
121                 resources = &motu->tx_resources;
122
123         err = amdtp_stream_start(stream, resources->channel,
124                                  fw_parent_device(motu->unit)->max_speed);
125         if (err < 0)
126                 return err;
127
128         if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT))
129                 return -ETIMEDOUT;
130
131         return 0;
132 }
133
134 int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
135 {
136         int err;
137
138         err = motu->spec->protocol->cache_packet_formats(motu);
139         if (err < 0)
140                 return err;
141
142         if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
143                 motu->tx_packet_formats.midi_flag_offset = 4;
144                 motu->tx_packet_formats.midi_byte_offset = 6;
145         } else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
146                 motu->tx_packet_formats.midi_flag_offset = 8;
147                 motu->tx_packet_formats.midi_byte_offset = 7;
148         }
149
150         if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
151                 motu->rx_packet_formats.midi_flag_offset = 4;
152                 motu->rx_packet_formats.midi_byte_offset = 6;
153         } else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
154                 motu->rx_packet_formats.midi_flag_offset = 8;
155                 motu->rx_packet_formats.midi_byte_offset = 7;
156         }
157
158         return 0;
159 }
160
161 int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate)
162 {
163         unsigned int curr_rate;
164         int err;
165
166         err = motu->spec->protocol->get_clock_rate(motu, &curr_rate);
167         if (err < 0)
168                 return err;
169         if (rate == 0)
170                 rate = curr_rate;
171
172         if (motu->substreams_counter == 0 || curr_rate != rate) {
173                 finish_session(motu);
174
175                 fw_iso_resources_free(&motu->tx_resources);
176                 fw_iso_resources_free(&motu->rx_resources);
177
178                 err = motu->spec->protocol->set_clock_rate(motu, rate);
179                 if (err < 0) {
180                         dev_err(&motu->unit->device,
181                                 "fail to set sampling rate: %d\n", err);
182                         return err;
183                 }
184
185                 err = snd_motu_stream_cache_packet_formats(motu);
186                 if (err < 0)
187                         return err;
188
189                 err = keep_resources(motu, rate, &motu->tx_stream);
190                 if (err < 0)
191                         return err;
192
193                 err = keep_resources(motu, rate, &motu->rx_stream);
194                 if (err < 0) {
195                         fw_iso_resources_free(&motu->tx_resources);
196                         return err;
197                 }
198         }
199
200         return 0;
201 }
202
203 static int ensure_packet_formats(struct snd_motu *motu)
204 {
205         __be32 reg;
206         u32 data;
207         int err;
208
209         err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
210                                         sizeof(reg));
211         if (err < 0)
212                 return err;
213         data = be32_to_cpu(reg);
214
215         data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
216                   RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
217                   TX_PACKET_TRANSMISSION_SPEED_MASK);
218         if (motu->tx_packet_formats.differed_part_pcm_chunks[0] == 0)
219                 data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
220         if (motu->rx_packet_formats.differed_part_pcm_chunks[0] == 0)
221                 data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
222         data |= fw_parent_device(motu->unit)->max_speed;
223
224         reg = cpu_to_be32(data);
225         return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
226                                           sizeof(reg));
227 }
228
229 int snd_motu_stream_start_duplex(struct snd_motu *motu)
230 {
231         unsigned int generation = motu->rx_resources.generation;
232         int err = 0;
233
234         if (motu->substreams_counter == 0)
235                 return 0;
236
237         if (amdtp_streaming_error(&motu->rx_stream) ||
238             amdtp_streaming_error(&motu->tx_stream))
239                 finish_session(motu);
240
241         if (generation != fw_parent_device(motu->unit)->card->generation) {
242                 err = fw_iso_resources_update(&motu->rx_resources);
243                 if (err < 0)
244                         return err;
245
246                 err = fw_iso_resources_update(&motu->tx_resources);
247                 if (err < 0)
248                         return err;
249         }
250
251         if (!amdtp_stream_running(&motu->rx_stream)) {
252                 err = ensure_packet_formats(motu);
253                 if (err < 0)
254                         return err;
255
256                 err = begin_session(motu);
257                 if (err < 0) {
258                         dev_err(&motu->unit->device,
259                                 "fail to start isochronous comm: %d\n", err);
260                         goto stop_streams;
261                 }
262
263                 err = start_isoc_ctx(motu, &motu->rx_stream);
264                 if (err < 0) {
265                         dev_err(&motu->unit->device,
266                                 "fail to start IT context: %d\n", err);
267                         goto stop_streams;
268                 }
269
270                 err = motu->spec->protocol->switch_fetching_mode(motu, true);
271                 if (err < 0) {
272                         dev_err(&motu->unit->device,
273                                 "fail to enable frame fetching: %d\n", err);
274                         goto stop_streams;
275                 }
276         }
277
278         if (!amdtp_stream_running(&motu->tx_stream)) {
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                         goto stop_streams;
284                 }
285         }
286
287         return 0;
288
289 stop_streams:
290         finish_session(motu);
291         return err;
292 }
293
294 void snd_motu_stream_stop_duplex(struct snd_motu *motu)
295 {
296         if (motu->substreams_counter == 0) {
297                 finish_session(motu);
298
299                 fw_iso_resources_free(&motu->tx_resources);
300                 fw_iso_resources_free(&motu->rx_resources);
301         }
302 }
303
304 static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir)
305 {
306         int err;
307         struct amdtp_stream *stream;
308         struct fw_iso_resources *resources;
309
310         if (dir == AMDTP_IN_STREAM) {
311                 stream = &motu->tx_stream;
312                 resources = &motu->tx_resources;
313         } else {
314                 stream = &motu->rx_stream;
315                 resources = &motu->rx_resources;
316         }
317
318         err = fw_iso_resources_init(resources, motu->unit);
319         if (err < 0)
320                 return err;
321
322         err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol);
323         if (err < 0) {
324                 amdtp_stream_destroy(stream);
325                 fw_iso_resources_destroy(resources);
326         }
327
328         return err;
329 }
330
331 static void destroy_stream(struct snd_motu *motu,
332                            enum amdtp_stream_direction dir)
333 {
334         struct amdtp_stream *stream;
335         struct fw_iso_resources *resources;
336
337         if (dir == AMDTP_IN_STREAM) {
338                 stream = &motu->tx_stream;
339                 resources = &motu->tx_resources;
340         } else {
341                 stream = &motu->rx_stream;
342                 resources = &motu->rx_resources;
343         }
344
345         amdtp_stream_destroy(stream);
346         fw_iso_resources_destroy(resources);
347 }
348
349 int snd_motu_stream_init_duplex(struct snd_motu *motu)
350 {
351         int err;
352
353         err = init_stream(motu, AMDTP_IN_STREAM);
354         if (err < 0)
355                 return err;
356
357         err = init_stream(motu, AMDTP_OUT_STREAM);
358         if (err < 0)
359                 destroy_stream(motu, AMDTP_IN_STREAM);
360
361         return err;
362 }
363
364 /*
365  * This function should be called before starting streams or after stopping
366  * streams.
367  */
368 void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
369 {
370         destroy_stream(motu, AMDTP_IN_STREAM);
371         destroy_stream(motu, AMDTP_OUT_STREAM);
372
373         motu->substreams_counter = 0;
374 }
375
376 static void motu_lock_changed(struct snd_motu *motu)
377 {
378         motu->dev_lock_changed = true;
379         wake_up(&motu->hwdep_wait);
380 }
381
382 int snd_motu_stream_lock_try(struct snd_motu *motu)
383 {
384         int err;
385
386         spin_lock_irq(&motu->lock);
387
388         if (motu->dev_lock_count < 0) {
389                 err = -EBUSY;
390                 goto out;
391         }
392
393         if (motu->dev_lock_count++ == 0)
394                 motu_lock_changed(motu);
395         err = 0;
396 out:
397         spin_unlock_irq(&motu->lock);
398         return err;
399 }
400
401 void snd_motu_stream_lock_release(struct snd_motu *motu)
402 {
403         spin_lock_irq(&motu->lock);
404
405         if (WARN_ON(motu->dev_lock_count <= 0))
406                 goto out;
407
408         if (--motu->dev_lock_count == 0)
409                 motu_lock_changed(motu);
410 out:
411         spin_unlock_irq(&motu->lock);
412 }