Merge tag 'sound-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[sfrench/cifs-2.6.git] / sound / firewire / tascam / tascam-stream.c
1 /*
2  * tascam-stream.c - a part of driver for TASCAM FireWire series
3  *
4  * Copyright (c) 2015 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8
9 #include <linux/delay.h>
10 #include "tascam.h"
11
12 #define CALLBACK_TIMEOUT 500
13
14 static int get_clock(struct snd_tscm *tscm, u32 *data)
15 {
16         __be32 reg;
17         int err;
18
19         err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
20                                  TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
21                                  &reg, sizeof(reg), 0);
22         if (err >= 0)
23                 *data = be32_to_cpu(reg);
24
25         return err;
26 }
27
28 static int set_clock(struct snd_tscm *tscm, unsigned int rate,
29                      enum snd_tscm_clock clock)
30 {
31         u32 data;
32         __be32 reg;
33         int err;
34
35         err = get_clock(tscm, &data);
36         if (err < 0)
37                 return err;
38         data &= 0x0000ffff;
39
40         if (rate > 0) {
41                 data &= 0x000000ff;
42                 /* Base rate. */
43                 if ((rate % 44100) == 0) {
44                         data |= 0x00000100;
45                         /* Multiplier. */
46                         if (rate / 44100 == 2)
47                                 data |= 0x00008000;
48                 } else if ((rate % 48000) == 0) {
49                         data |= 0x00000200;
50                         /* Multiplier. */
51                         if (rate / 48000 == 2)
52                                 data |= 0x00008000;
53                 } else {
54                         return -EAGAIN;
55                 }
56         }
57
58         if (clock != INT_MAX) {
59                 data &= 0x0000ff00;
60                 data |= clock + 1;
61         }
62
63         reg = cpu_to_be32(data);
64
65         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
66                                  TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
67                                  &reg, sizeof(reg), 0);
68         if (err < 0)
69                 return err;
70
71         if (data & 0x00008000)
72                 reg = cpu_to_be32(0x0000001a);
73         else
74                 reg = cpu_to_be32(0x0000000d);
75
76         return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
77                                   TSCM_ADDR_BASE + TSCM_OFFSET_MULTIPLEX_MODE,
78                                   &reg, sizeof(reg), 0);
79 }
80
81 int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate)
82 {
83         u32 data = 0x0;
84         unsigned int trials = 0;
85         int err;
86
87         while (data == 0x0 || trials++ < 5) {
88                 err = get_clock(tscm, &data);
89                 if (err < 0)
90                         return err;
91
92                 data = (data & 0xff000000) >> 24;
93         }
94
95         /* Check base rate. */
96         if ((data & 0x0f) == 0x01)
97                 *rate = 44100;
98         else if ((data & 0x0f) == 0x02)
99                 *rate = 48000;
100         else
101                 return -EAGAIN;
102
103         /* Check multiplier. */
104         if ((data & 0xf0) == 0x80)
105                 *rate *= 2;
106         else if ((data & 0xf0) != 0x00)
107                 return -EAGAIN;
108
109         return err;
110 }
111
112 int snd_tscm_stream_get_clock(struct snd_tscm *tscm, enum snd_tscm_clock *clock)
113 {
114         u32 data;
115         int err;
116
117         err = get_clock(tscm, &data);
118         if (err < 0)
119                 return err;
120
121         *clock = ((data & 0x00ff0000) >> 16) - 1;
122         if (*clock < 0 || *clock > SND_TSCM_CLOCK_ADAT)
123                 return -EIO;
124
125         return 0;
126 }
127
128 static int enable_data_channels(struct snd_tscm *tscm)
129 {
130         __be32 reg;
131         u32 data;
132         unsigned int i;
133         int err;
134
135         data = 0;
136         for (i = 0; i < tscm->spec->pcm_capture_analog_channels; ++i)
137                 data |= BIT(i);
138         if (tscm->spec->has_adat)
139                 data |= 0x0000ff00;
140         if (tscm->spec->has_spdif)
141                 data |= 0x00030000;
142
143         reg = cpu_to_be32(data);
144         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
145                                  TSCM_ADDR_BASE + TSCM_OFFSET_TX_PCM_CHANNELS,
146                                  &reg, sizeof(reg), 0);
147         if (err < 0)
148                 return err;
149
150         data = 0;
151         for (i = 0; i < tscm->spec->pcm_playback_analog_channels; ++i)
152                 data |= BIT(i);
153         if (tscm->spec->has_adat)
154                 data |= 0x0000ff00;
155         if (tscm->spec->has_spdif)
156                 data |= 0x00030000;
157
158         reg = cpu_to_be32(data);
159         return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
160                                   TSCM_ADDR_BASE + TSCM_OFFSET_RX_PCM_CHANNELS,
161                                   &reg, sizeof(reg), 0);
162 }
163
164 static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate)
165 {
166         __be32 reg;
167         int err;
168
169         /* Set an option for unknown purpose. */
170         reg = cpu_to_be32(0x00200000);
171         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
172                                  TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
173                                  &reg, sizeof(reg), 0);
174         if (err < 0)
175                 return err;
176
177         err = enable_data_channels(tscm);
178         if (err < 0)
179                 return err;
180
181         return set_clock(tscm, rate, INT_MAX);
182 }
183
184 static void finish_session(struct snd_tscm *tscm)
185 {
186         __be32 reg;
187
188         reg = 0;
189         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
190                            TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
191                            &reg, sizeof(reg), 0);
192
193         reg = 0;
194         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
195                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
196                            &reg, sizeof(reg), 0);
197
198 }
199
200 static int begin_session(struct snd_tscm *tscm)
201 {
202         __be32 reg;
203         int err;
204
205         reg = cpu_to_be32(0x00000001);
206         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
207                                  TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
208                                  &reg, sizeof(reg), 0);
209         if (err < 0)
210                 return err;
211
212         reg = cpu_to_be32(0x00000001);
213         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
214                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
215                                  &reg, sizeof(reg), 0);
216         if (err < 0)
217                 return err;
218
219         /* Set an option for unknown purpose. */
220         reg = cpu_to_be32(0x00002000);
221         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
222                                  TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
223                                  &reg, sizeof(reg), 0);
224         if (err < 0)
225                 return err;
226
227         /* Start multiplexing PCM samples on packets. */
228         reg = cpu_to_be32(0x00000001);
229         return snd_fw_transaction(tscm->unit,
230                                   TCODE_WRITE_QUADLET_REQUEST,
231                                   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON,
232                                   &reg, sizeof(reg), 0);
233 }
234
235 static void release_resources(struct snd_tscm *tscm)
236 {
237         __be32 reg;
238
239         /* Unregister channels. */
240         reg = cpu_to_be32(0x00000000);
241         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
242                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
243                            &reg, sizeof(reg), 0);
244         reg = cpu_to_be32(0x00000000);
245         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
246                            TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
247                            &reg, sizeof(reg), 0);
248         reg = cpu_to_be32(0x00000000);
249         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
250                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
251                            &reg, sizeof(reg), 0);
252
253         /* Release isochronous resources. */
254         fw_iso_resources_free(&tscm->tx_resources);
255         fw_iso_resources_free(&tscm->rx_resources);
256 }
257
258 static int keep_resources(struct snd_tscm *tscm, unsigned int rate)
259 {
260         __be32 reg;
261         int err;
262
263         /* Keep resources for in-stream. */
264         err = amdtp_tscm_set_parameters(&tscm->tx_stream, rate);
265         if (err < 0)
266                 return err;
267         err = fw_iso_resources_allocate(&tscm->tx_resources,
268                         amdtp_stream_get_max_payload(&tscm->tx_stream),
269                         fw_parent_device(tscm->unit)->max_speed);
270         if (err < 0)
271                 goto error;
272
273         /* Keep resources for out-stream. */
274         err = amdtp_tscm_set_parameters(&tscm->rx_stream, rate);
275         if (err < 0)
276                 return err;
277         err = fw_iso_resources_allocate(&tscm->rx_resources,
278                         amdtp_stream_get_max_payload(&tscm->rx_stream),
279                         fw_parent_device(tscm->unit)->max_speed);
280         if (err < 0)
281                 return err;
282
283         /* Register the isochronous channel for transmitting stream. */
284         reg = cpu_to_be32(tscm->tx_resources.channel);
285         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
286                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
287                                  &reg, sizeof(reg), 0);
288         if (err < 0)
289                 goto error;
290
291         /* Unknown */
292         reg = cpu_to_be32(0x00000002);
293         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
294                                  TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
295                                  &reg, sizeof(reg), 0);
296         if (err < 0)
297                 goto error;
298
299         /* Register the isochronous channel for receiving stream. */
300         reg = cpu_to_be32(tscm->rx_resources.channel);
301         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
302                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
303                                  &reg, sizeof(reg), 0);
304         if (err < 0)
305                 goto error;
306
307         return 0;
308 error:
309         release_resources(tscm);
310         return err;
311 }
312
313 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
314 {
315         unsigned int pcm_channels;
316         int err;
317
318         /* For out-stream. */
319         err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit);
320         if (err < 0)
321                 return err;
322         pcm_channels = tscm->spec->pcm_playback_analog_channels;
323         if (tscm->spec->has_adat)
324                 pcm_channels += 8;
325         if (tscm->spec->has_spdif)
326                 pcm_channels += 2;
327         err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM,
328                               pcm_channels);
329         if (err < 0)
330                 return err;
331
332         /* For in-stream. */
333         err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit);
334         if (err < 0)
335                 return err;
336         pcm_channels = tscm->spec->pcm_capture_analog_channels;
337         if (tscm->spec->has_adat)
338                 pcm_channels += 8;
339         if (tscm->spec->has_spdif)
340                 pcm_channels += 2;
341         err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM,
342                               pcm_channels);
343         if (err < 0)
344                 amdtp_stream_destroy(&tscm->rx_stream);
345
346         return 0;
347 }
348
349 /* At bus reset, streaming is stopped and some registers are clear. */
350 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
351 {
352         amdtp_stream_pcm_abort(&tscm->tx_stream);
353         amdtp_stream_stop(&tscm->tx_stream);
354
355         amdtp_stream_pcm_abort(&tscm->rx_stream);
356         amdtp_stream_stop(&tscm->rx_stream);
357 }
358
359 /*
360  * This function should be called before starting streams or after stopping
361  * streams.
362  */
363 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
364 {
365         amdtp_stream_destroy(&tscm->rx_stream);
366         amdtp_stream_destroy(&tscm->tx_stream);
367
368         fw_iso_resources_destroy(&tscm->rx_resources);
369         fw_iso_resources_destroy(&tscm->tx_resources);
370 }
371
372 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
373 {
374         unsigned int curr_rate;
375         int err;
376
377         if (tscm->substreams_counter == 0)
378                 return 0;
379
380         err = snd_tscm_stream_get_rate(tscm, &curr_rate);
381         if (err < 0)
382                 return err;
383         if (curr_rate != rate ||
384             amdtp_streaming_error(&tscm->rx_stream) ||
385             amdtp_streaming_error(&tscm->tx_stream)) {
386                 finish_session(tscm);
387
388                 amdtp_stream_stop(&tscm->rx_stream);
389                 amdtp_stream_stop(&tscm->tx_stream);
390
391                 release_resources(tscm);
392         }
393
394         if (!amdtp_stream_running(&tscm->rx_stream)) {
395                 err = keep_resources(tscm, rate);
396                 if (err < 0)
397                         goto error;
398
399                 err = set_stream_formats(tscm, rate);
400                 if (err < 0)
401                         goto error;
402
403                 err = begin_session(tscm);
404                 if (err < 0)
405                         goto error;
406
407                 err = amdtp_stream_start(&tscm->rx_stream,
408                                 tscm->rx_resources.channel,
409                                 fw_parent_device(tscm->unit)->max_speed);
410                 if (err < 0)
411                         goto error;
412
413                 if (!amdtp_stream_wait_callback(&tscm->rx_stream,
414                                                 CALLBACK_TIMEOUT)) {
415                         err = -ETIMEDOUT;
416                         goto error;
417                 }
418         }
419
420         if (!amdtp_stream_running(&tscm->tx_stream)) {
421                 err = amdtp_stream_start(&tscm->tx_stream,
422                                 tscm->tx_resources.channel,
423                                 fw_parent_device(tscm->unit)->max_speed);
424                 if (err < 0)
425                         goto error;
426
427                 if (!amdtp_stream_wait_callback(&tscm->tx_stream,
428                                                 CALLBACK_TIMEOUT)) {
429                         err = -ETIMEDOUT;
430                         goto error;
431                 }
432         }
433
434         return 0;
435 error:
436         amdtp_stream_stop(&tscm->rx_stream);
437         amdtp_stream_stop(&tscm->tx_stream);
438
439         finish_session(tscm);
440         release_resources(tscm);
441
442         return err;
443 }
444
445 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
446 {
447         if (tscm->substreams_counter > 0)
448                 return;
449
450         amdtp_stream_stop(&tscm->tx_stream);
451         amdtp_stream_stop(&tscm->rx_stream);
452
453         finish_session(tscm);
454         release_resources(tscm);
455 }
456
457 void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
458 {
459         tscm->dev_lock_changed = true;
460         wake_up(&tscm->hwdep_wait);
461 }
462
463 int snd_tscm_stream_lock_try(struct snd_tscm *tscm)
464 {
465         int err;
466
467         spin_lock_irq(&tscm->lock);
468
469         /* user land lock this */
470         if (tscm->dev_lock_count < 0) {
471                 err = -EBUSY;
472                 goto end;
473         }
474
475         /* this is the first time */
476         if (tscm->dev_lock_count++ == 0)
477                 snd_tscm_stream_lock_changed(tscm);
478         err = 0;
479 end:
480         spin_unlock_irq(&tscm->lock);
481         return err;
482 }
483
484 void snd_tscm_stream_lock_release(struct snd_tscm *tscm)
485 {
486         spin_lock_irq(&tscm->lock);
487
488         if (WARN_ON(tscm->dev_lock_count <= 0))
489                 goto end;
490         if (--tscm->dev_lock_count == 0)
491                 snd_tscm_stream_lock_changed(tscm);
492 end:
493         spin_unlock_irq(&tscm->lock);
494 }