e852e46ebe6fa6c9bf77ce579f214c997cb67680
[linux-2.6-block.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         return enable_data_channels(tscm);
177 }
178
179 static void finish_session(struct snd_tscm *tscm)
180 {
181         __be32 reg;
182
183         amdtp_stream_stop(&tscm->rx_stream);
184         amdtp_stream_stop(&tscm->tx_stream);
185
186         reg = 0;
187         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
188                            TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
189                            &reg, sizeof(reg), 0);
190
191         reg = 0;
192         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
193                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
194                            &reg, sizeof(reg), 0);
195
196         // Unregister channels.
197         reg = cpu_to_be32(0x00000000);
198         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
199                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
200                            &reg, sizeof(reg), 0);
201         reg = cpu_to_be32(0x00000000);
202         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
203                            TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
204                            &reg, sizeof(reg), 0);
205         reg = cpu_to_be32(0x00000000);
206         snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
207                            TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
208                            &reg, sizeof(reg), 0);
209 }
210
211 static int begin_session(struct snd_tscm *tscm)
212 {
213         __be32 reg;
214         int err;
215
216         // Register the isochronous channel for transmitting stream.
217         reg = cpu_to_be32(tscm->tx_resources.channel);
218         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
219                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
220                                  &reg, sizeof(reg), 0);
221         if (err < 0)
222                 return err;
223
224         // Unknown.
225         reg = cpu_to_be32(0x00000002);
226         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
227                                  TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
228                                  &reg, sizeof(reg), 0);
229         if (err < 0)
230                 return err;
231
232         // Register the isochronous channel for receiving stream.
233         reg = cpu_to_be32(tscm->rx_resources.channel);
234         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
235                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
236                                  &reg, sizeof(reg), 0);
237         if (err < 0)
238                 return err;
239
240         reg = cpu_to_be32(0x00000001);
241         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
242                                  TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
243                                  &reg, sizeof(reg), 0);
244         if (err < 0)
245                 return err;
246
247         reg = cpu_to_be32(0x00000001);
248         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
249                                  TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
250                                  &reg, sizeof(reg), 0);
251         if (err < 0)
252                 return err;
253
254         // Set an option for unknown purpose.
255         reg = cpu_to_be32(0x00002000);
256         err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
257                                  TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
258                                  &reg, sizeof(reg), 0);
259         if (err < 0)
260                 return err;
261
262         // Start multiplexing PCM samples on packets.
263         reg = cpu_to_be32(0x00000001);
264         return snd_fw_transaction(tscm->unit,
265                                   TCODE_WRITE_QUADLET_REQUEST,
266                                   TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_ON,
267                                   &reg, sizeof(reg), 0);
268 }
269
270 static int keep_resources(struct snd_tscm *tscm, unsigned int rate,
271                           struct amdtp_stream *stream)
272 {
273         struct fw_iso_resources *resources;
274         int err;
275
276         if (stream == &tscm->tx_stream)
277                 resources = &tscm->tx_resources;
278         else
279                 resources = &tscm->rx_resources;
280
281         err = amdtp_tscm_set_parameters(stream, rate);
282         if (err < 0)
283                 return err;
284
285         return fw_iso_resources_allocate(resources,
286                                 amdtp_stream_get_max_payload(stream),
287                                 fw_parent_device(tscm->unit)->max_speed);
288 }
289
290 int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
291 {
292         unsigned int pcm_channels;
293         int err;
294
295         /* For out-stream. */
296         err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit);
297         if (err < 0)
298                 return err;
299         pcm_channels = tscm->spec->pcm_playback_analog_channels;
300         if (tscm->spec->has_adat)
301                 pcm_channels += 8;
302         if (tscm->spec->has_spdif)
303                 pcm_channels += 2;
304         err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM,
305                               pcm_channels);
306         if (err < 0)
307                 return err;
308
309         /* For in-stream. */
310         err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit);
311         if (err < 0)
312                 return err;
313         pcm_channels = tscm->spec->pcm_capture_analog_channels;
314         if (tscm->spec->has_adat)
315                 pcm_channels += 8;
316         if (tscm->spec->has_spdif)
317                 pcm_channels += 2;
318         err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM,
319                               pcm_channels);
320         if (err < 0)
321                 amdtp_stream_destroy(&tscm->rx_stream);
322
323         return err;
324 }
325
326 // At bus reset, streaming is stopped and some registers are clear.
327 void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
328 {
329         amdtp_stream_pcm_abort(&tscm->tx_stream);
330         amdtp_stream_stop(&tscm->tx_stream);
331
332         amdtp_stream_pcm_abort(&tscm->rx_stream);
333         amdtp_stream_stop(&tscm->rx_stream);
334 }
335
336 /*
337  * This function should be called before starting streams or after stopping
338  * streams.
339  */
340 void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
341 {
342         amdtp_stream_destroy(&tscm->rx_stream);
343         amdtp_stream_destroy(&tscm->tx_stream);
344
345         fw_iso_resources_destroy(&tscm->rx_resources);
346         fw_iso_resources_destroy(&tscm->tx_resources);
347 }
348
349 int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate)
350 {
351         unsigned int curr_rate;
352         int err;
353
354         err = snd_tscm_stream_get_rate(tscm, &curr_rate);
355         if (err < 0)
356                 return err;
357
358         if (tscm->substreams_counter == 0 || rate != curr_rate) {
359                 finish_session(tscm);
360
361                 fw_iso_resources_free(&tscm->tx_resources);
362                 fw_iso_resources_free(&tscm->rx_resources);
363
364                 err = set_clock(tscm, rate, INT_MAX);
365                 if (err < 0)
366                         return err;
367
368                 err = keep_resources(tscm, rate, &tscm->tx_stream);
369                 if (err < 0)
370                         return err;
371
372                 err = keep_resources(tscm, rate, &tscm->rx_stream);
373                 if (err < 0) {
374                         fw_iso_resources_free(&tscm->tx_resources);
375                         return err;
376                 }
377         }
378
379         return 0;
380 }
381
382 int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
383 {
384         unsigned int generation = tscm->rx_resources.generation;
385         int err;
386
387         if (tscm->substreams_counter == 0)
388                 return 0;
389
390         if (amdtp_streaming_error(&tscm->rx_stream) ||
391             amdtp_streaming_error(&tscm->tx_stream))
392                 finish_session(tscm);
393
394         if (generation != fw_parent_device(tscm->unit)->card->generation) {
395                 err = fw_iso_resources_update(&tscm->tx_resources);
396                 if (err < 0)
397                         goto error;
398
399                 err = fw_iso_resources_update(&tscm->rx_resources);
400                 if (err < 0)
401                         goto error;
402         }
403
404         if (!amdtp_stream_running(&tscm->rx_stream)) {
405                 err = set_stream_formats(tscm, rate);
406                 if (err < 0)
407                         goto error;
408
409                 err = begin_session(tscm);
410                 if (err < 0)
411                         goto error;
412
413                 err = amdtp_stream_start(&tscm->rx_stream,
414                                 tscm->rx_resources.channel,
415                                 fw_parent_device(tscm->unit)->max_speed);
416                 if (err < 0)
417                         goto error;
418
419                 if (!amdtp_stream_wait_callback(&tscm->rx_stream,
420                                                 CALLBACK_TIMEOUT)) {
421                         err = -ETIMEDOUT;
422                         goto error;
423                 }
424         }
425
426         if (!amdtp_stream_running(&tscm->tx_stream)) {
427                 err = amdtp_stream_start(&tscm->tx_stream,
428                                 tscm->tx_resources.channel,
429                                 fw_parent_device(tscm->unit)->max_speed);
430                 if (err < 0)
431                         goto error;
432
433                 if (!amdtp_stream_wait_callback(&tscm->tx_stream,
434                                                 CALLBACK_TIMEOUT)) {
435                         err = -ETIMEDOUT;
436                         goto error;
437                 }
438         }
439
440         return 0;
441 error:
442         finish_session(tscm);
443
444         return err;
445 }
446
447 void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
448 {
449         if (tscm->substreams_counter == 0) {
450                 finish_session(tscm);
451
452                 fw_iso_resources_free(&tscm->tx_resources);
453                 fw_iso_resources_free(&tscm->rx_resources);
454         }
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 }