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