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