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