2 * tascam-stream.c - a part of driver for TASCAM FireWire series
4 * Copyright (c) 2015 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
9 #include <linux/delay.h>
12 #define CLOCK_STATUS_MASK 0xffff0000
13 #define CLOCK_CONFIG_MASK 0x0000ffff
15 #define CALLBACK_TIMEOUT 500
17 static int get_clock(struct snd_tscm
*tscm
, u32
*data
)
24 err
= snd_fw_transaction(tscm
->unit
, TCODE_READ_QUADLET_REQUEST
,
25 TSCM_ADDR_BASE
+ TSCM_OFFSET_CLOCK_STATUS
,
26 ®
, sizeof(reg
), 0);
30 *data
= be32_to_cpu(reg
);
31 if (*data
& CLOCK_STATUS_MASK
)
34 // In intermediate state after changing clock status.
38 // Still in the intermediate state.
45 static int set_clock(struct snd_tscm
*tscm
, unsigned int rate
,
46 enum snd_tscm_clock clock
)
52 err
= get_clock(tscm
, &data
);
55 data
&= CLOCK_CONFIG_MASK
;
60 if ((rate
% 44100) == 0) {
63 if (rate
/ 44100 == 2)
65 } else if ((rate
% 48000) == 0) {
68 if (rate
/ 48000 == 2)
75 if (clock
!= INT_MAX
) {
80 reg
= cpu_to_be32(data
);
82 err
= snd_fw_transaction(tscm
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
83 TSCM_ADDR_BASE
+ TSCM_OFFSET_CLOCK_STATUS
,
84 ®
, sizeof(reg
), 0);
88 if (data
& 0x00008000)
89 reg
= cpu_to_be32(0x0000001a);
91 reg
= cpu_to_be32(0x0000000d);
93 return snd_fw_transaction(tscm
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
94 TSCM_ADDR_BASE
+ TSCM_OFFSET_MULTIPLEX_MODE
,
95 ®
, sizeof(reg
), 0);
98 int snd_tscm_stream_get_rate(struct snd_tscm
*tscm
, unsigned int *rate
)
103 err
= get_clock(tscm
, &data
);
107 data
= (data
& 0xff000000) >> 24;
109 /* Check base rate. */
110 if ((data
& 0x0f) == 0x01)
112 else if ((data
& 0x0f) == 0x02)
117 /* Check multiplier. */
118 if ((data
& 0xf0) == 0x80)
120 else if ((data
& 0xf0) != 0x00)
126 int snd_tscm_stream_get_clock(struct snd_tscm
*tscm
, enum snd_tscm_clock
*clock
)
131 err
= get_clock(tscm
, &data
);
135 *clock
= ((data
& 0x00ff0000) >> 16) - 1;
136 if (*clock
< 0 || *clock
> SND_TSCM_CLOCK_ADAT
)
142 static int enable_data_channels(struct snd_tscm
*tscm
)
150 for (i
= 0; i
< tscm
->spec
->pcm_capture_analog_channels
; ++i
)
152 if (tscm
->spec
->has_adat
)
154 if (tscm
->spec
->has_spdif
)
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 ®
, sizeof(reg
), 0);
165 for (i
= 0; i
< tscm
->spec
->pcm_playback_analog_channels
; ++i
)
167 if (tscm
->spec
->has_adat
)
169 if (tscm
->spec
->has_spdif
)
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 ®
, sizeof(reg
), 0);
178 static int set_stream_formats(struct snd_tscm
*tscm
, unsigned int rate
)
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 ®
, sizeof(reg
), 0);
191 err
= enable_data_channels(tscm
);
195 return set_clock(tscm
, rate
, INT_MAX
);
198 static void finish_session(struct snd_tscm
*tscm
)
203 snd_fw_transaction(tscm
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
204 TSCM_ADDR_BASE
+ TSCM_OFFSET_START_STREAMING
,
205 ®
, sizeof(reg
), 0);
208 snd_fw_transaction(tscm
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
209 TSCM_ADDR_BASE
+ TSCM_OFFSET_ISOC_RX_ON
,
210 ®
, sizeof(reg
), 0);
214 static int begin_session(struct snd_tscm
*tscm
)
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 ®
, sizeof(reg
), 0);
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 ®
, sizeof(reg
), 0);
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 ®
, sizeof(reg
), 0);
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 ®
, sizeof(reg
), 0);
249 static void release_resources(struct snd_tscm
*tscm
)
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 ®
, 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 ®
, 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 ®
, sizeof(reg
), 0);
267 /* Release isochronous resources. */
268 fw_iso_resources_free(&tscm
->tx_resources
);
269 fw_iso_resources_free(&tscm
->rx_resources
);
272 static int keep_resources(struct snd_tscm
*tscm
, unsigned int rate
)
277 /* Keep resources for in-stream. */
278 err
= amdtp_tscm_set_parameters(&tscm
->tx_stream
, rate
);
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
);
287 /* Keep resources for out-stream. */
288 err
= amdtp_tscm_set_parameters(&tscm
->rx_stream
, rate
);
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
);
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 ®
, sizeof(reg
), 0);
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 ®
, sizeof(reg
), 0);
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 ®
, sizeof(reg
), 0);
323 release_resources(tscm
);
327 int snd_tscm_stream_init_duplex(struct snd_tscm
*tscm
)
329 unsigned int pcm_channels
;
332 /* For out-stream. */
333 err
= fw_iso_resources_init(&tscm
->rx_resources
, tscm
->unit
);
336 pcm_channels
= tscm
->spec
->pcm_playback_analog_channels
;
337 if (tscm
->spec
->has_adat
)
339 if (tscm
->spec
->has_spdif
)
341 err
= amdtp_tscm_init(&tscm
->rx_stream
, tscm
->unit
, AMDTP_OUT_STREAM
,
347 err
= fw_iso_resources_init(&tscm
->tx_resources
, tscm
->unit
);
350 pcm_channels
= tscm
->spec
->pcm_capture_analog_channels
;
351 if (tscm
->spec
->has_adat
)
353 if (tscm
->spec
->has_spdif
)
355 err
= amdtp_tscm_init(&tscm
->tx_stream
, tscm
->unit
, AMDTP_IN_STREAM
,
358 amdtp_stream_destroy(&tscm
->rx_stream
);
363 /* At bus reset, streaming is stopped and some registers are clear. */
364 void snd_tscm_stream_update_duplex(struct snd_tscm
*tscm
)
366 amdtp_stream_pcm_abort(&tscm
->tx_stream
);
367 amdtp_stream_stop(&tscm
->tx_stream
);
369 amdtp_stream_pcm_abort(&tscm
->rx_stream
);
370 amdtp_stream_stop(&tscm
->rx_stream
);
374 * This function should be called before starting streams or after stopping
377 void snd_tscm_stream_destroy_duplex(struct snd_tscm
*tscm
)
379 amdtp_stream_destroy(&tscm
->rx_stream
);
380 amdtp_stream_destroy(&tscm
->tx_stream
);
382 fw_iso_resources_destroy(&tscm
->rx_resources
);
383 fw_iso_resources_destroy(&tscm
->tx_resources
);
386 int snd_tscm_stream_start_duplex(struct snd_tscm
*tscm
, unsigned int rate
)
388 unsigned int curr_rate
;
391 if (tscm
->substreams_counter
== 0)
394 err
= snd_tscm_stream_get_rate(tscm
, &curr_rate
);
397 if (curr_rate
!= rate
||
398 amdtp_streaming_error(&tscm
->rx_stream
) ||
399 amdtp_streaming_error(&tscm
->tx_stream
)) {
400 finish_session(tscm
);
402 amdtp_stream_stop(&tscm
->rx_stream
);
403 amdtp_stream_stop(&tscm
->tx_stream
);
405 release_resources(tscm
);
408 if (!amdtp_stream_running(&tscm
->rx_stream
)) {
409 err
= keep_resources(tscm
, rate
);
413 err
= set_stream_formats(tscm
, rate
);
417 err
= begin_session(tscm
);
421 err
= amdtp_stream_start(&tscm
->rx_stream
,
422 tscm
->rx_resources
.channel
,
423 fw_parent_device(tscm
->unit
)->max_speed
);
427 if (!amdtp_stream_wait_callback(&tscm
->rx_stream
,
434 if (!amdtp_stream_running(&tscm
->tx_stream
)) {
435 err
= amdtp_stream_start(&tscm
->tx_stream
,
436 tscm
->tx_resources
.channel
,
437 fw_parent_device(tscm
->unit
)->max_speed
);
441 if (!amdtp_stream_wait_callback(&tscm
->tx_stream
,
450 amdtp_stream_stop(&tscm
->rx_stream
);
451 amdtp_stream_stop(&tscm
->tx_stream
);
453 finish_session(tscm
);
454 release_resources(tscm
);
459 void snd_tscm_stream_stop_duplex(struct snd_tscm
*tscm
)
461 if (tscm
->substreams_counter
> 0)
464 amdtp_stream_stop(&tscm
->tx_stream
);
465 amdtp_stream_stop(&tscm
->rx_stream
);
467 finish_session(tscm
);
468 release_resources(tscm
);
471 void snd_tscm_stream_lock_changed(struct snd_tscm
*tscm
)
473 tscm
->dev_lock_changed
= true;
474 wake_up(&tscm
->hwdep_wait
);
477 int snd_tscm_stream_lock_try(struct snd_tscm
*tscm
)
481 spin_lock_irq(&tscm
->lock
);
483 /* user land lock this */
484 if (tscm
->dev_lock_count
< 0) {
489 /* this is the first time */
490 if (tscm
->dev_lock_count
++ == 0)
491 snd_tscm_stream_lock_changed(tscm
);
494 spin_unlock_irq(&tscm
->lock
);
498 void snd_tscm_stream_lock_release(struct snd_tscm
*tscm
)
500 spin_lock_irq(&tscm
->lock
);
502 if (WARN_ON(tscm
->dev_lock_count
<= 0))
504 if (--tscm
->dev_lock_count
== 0)
505 snd_tscm_stream_lock_changed(tscm
);
507 spin_unlock_irq(&tscm
->lock
);