2 * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
4 * Copyright (c) 2014-2015 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 #define CALLBACK_TIMEOUT 500
13 const unsigned int snd_dg00x_stream_rates
[SND_DG00X_RATE_COUNT
] = {
14 [SND_DG00X_RATE_44100
] = 44100,
15 [SND_DG00X_RATE_48000
] = 48000,
16 [SND_DG00X_RATE_88200
] = 88200,
17 [SND_DG00X_RATE_96000
] = 96000,
20 /* Multi Bit Linear Audio data channels for each sampling transfer frequency. */
22 snd_dg00x_stream_pcm_channels
[SND_DG00X_RATE_COUNT
] = {
23 /* Analog/ADAT/SPDIF */
24 [SND_DG00X_RATE_44100
] = (8 + 8 + 2),
25 [SND_DG00X_RATE_48000
] = (8 + 8 + 2),
27 [SND_DG00X_RATE_88200
] = (8 + 2),
28 [SND_DG00X_RATE_96000
] = (8 + 2),
31 int snd_dg00x_stream_get_local_rate(struct snd_dg00x
*dg00x
, unsigned int *rate
)
37 err
= snd_fw_transaction(dg00x
->unit
, TCODE_READ_QUADLET_REQUEST
,
38 DG00X_ADDR_BASE
+ DG00X_OFFSET_LOCAL_RATE
,
39 ®
, sizeof(reg
), 0);
43 data
= be32_to_cpu(reg
) & 0x0f;
44 if (data
< ARRAY_SIZE(snd_dg00x_stream_rates
))
45 *rate
= snd_dg00x_stream_rates
[data
];
52 int snd_dg00x_stream_set_local_rate(struct snd_dg00x
*dg00x
, unsigned int rate
)
57 for (i
= 0; i
< ARRAY_SIZE(snd_dg00x_stream_rates
); i
++) {
58 if (rate
== snd_dg00x_stream_rates
[i
])
61 if (i
== ARRAY_SIZE(snd_dg00x_stream_rates
))
65 return snd_fw_transaction(dg00x
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
66 DG00X_ADDR_BASE
+ DG00X_OFFSET_LOCAL_RATE
,
67 ®
, sizeof(reg
), 0);
70 int snd_dg00x_stream_get_clock(struct snd_dg00x
*dg00x
,
71 enum snd_dg00x_clock
*clock
)
76 err
= snd_fw_transaction(dg00x
->unit
, TCODE_READ_QUADLET_REQUEST
,
77 DG00X_ADDR_BASE
+ DG00X_OFFSET_CLOCK_SOURCE
,
78 ®
, sizeof(reg
), 0);
82 *clock
= be32_to_cpu(reg
) & 0x0f;
83 if (*clock
>= SND_DG00X_CLOCK_COUNT
)
89 int snd_dg00x_stream_check_external_clock(struct snd_dg00x
*dg00x
, bool *detect
)
94 err
= snd_fw_transaction(dg00x
->unit
, TCODE_READ_QUADLET_REQUEST
,
95 DG00X_ADDR_BASE
+ DG00X_OFFSET_DETECT_EXTERNAL
,
96 ®
, sizeof(reg
), 0);
98 *detect
= be32_to_cpu(reg
) > 0;
103 int snd_dg00x_stream_get_external_rate(struct snd_dg00x
*dg00x
,
110 err
= snd_fw_transaction(dg00x
->unit
, TCODE_READ_QUADLET_REQUEST
,
111 DG00X_ADDR_BASE
+ DG00X_OFFSET_EXTERNAL_RATE
,
112 ®
, sizeof(reg
), 0);
116 data
= be32_to_cpu(reg
) & 0x0f;
117 if (data
< ARRAY_SIZE(snd_dg00x_stream_rates
))
118 *rate
= snd_dg00x_stream_rates
[data
];
119 /* This means desync. */
126 static void finish_session(struct snd_dg00x
*dg00x
)
128 __be32 data
= cpu_to_be32(0x00000003);
130 snd_fw_transaction(dg00x
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
131 DG00X_ADDR_BASE
+ DG00X_OFFSET_STREAMING_SET
,
132 &data
, sizeof(data
), 0);
135 static int begin_session(struct snd_dg00x
*dg00x
)
141 err
= snd_fw_transaction(dg00x
->unit
, TCODE_READ_QUADLET_REQUEST
,
142 DG00X_ADDR_BASE
+ DG00X_OFFSET_STREAMING_STATE
,
143 &data
, sizeof(data
), 0);
146 curr
= be32_to_cpu(data
);
153 data
= cpu_to_be32(curr
);
154 err
= snd_fw_transaction(dg00x
->unit
,
155 TCODE_WRITE_QUADLET_REQUEST
,
157 DG00X_OFFSET_STREAMING_SET
,
158 &data
, sizeof(data
), 0);
168 finish_session(dg00x
);
172 static void release_resources(struct snd_dg00x
*dg00x
)
176 /* Unregister isochronous channels for both direction. */
177 snd_fw_transaction(dg00x
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
178 DG00X_ADDR_BASE
+ DG00X_OFFSET_ISOC_CHANNELS
,
179 &data
, sizeof(data
), 0);
181 /* Release isochronous resources. */
182 fw_iso_resources_free(&dg00x
->tx_resources
);
183 fw_iso_resources_free(&dg00x
->rx_resources
);
186 static int keep_resources(struct snd_dg00x
*dg00x
, unsigned int rate
)
192 /* Check sampling rate. */
193 for (i
= 0; i
< SND_DG00X_RATE_COUNT
; i
++) {
194 if (snd_dg00x_stream_rates
[i
] == rate
)
197 if (i
== SND_DG00X_RATE_COUNT
)
200 /* Keep resources for out-stream. */
201 err
= amdtp_dot_set_parameters(&dg00x
->rx_stream
, rate
,
202 snd_dg00x_stream_pcm_channels
[i
]);
205 err
= fw_iso_resources_allocate(&dg00x
->rx_resources
,
206 amdtp_stream_get_max_payload(&dg00x
->rx_stream
),
207 fw_parent_device(dg00x
->unit
)->max_speed
);
211 /* Keep resources for in-stream. */
212 err
= amdtp_dot_set_parameters(&dg00x
->tx_stream
, rate
,
213 snd_dg00x_stream_pcm_channels
[i
]);
216 err
= fw_iso_resources_allocate(&dg00x
->tx_resources
,
217 amdtp_stream_get_max_payload(&dg00x
->tx_stream
),
218 fw_parent_device(dg00x
->unit
)->max_speed
);
222 /* Register isochronous channels for both direction. */
223 data
= cpu_to_be32((dg00x
->tx_resources
.channel
<< 16) |
224 dg00x
->rx_resources
.channel
);
225 err
= snd_fw_transaction(dg00x
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
226 DG00X_ADDR_BASE
+ DG00X_OFFSET_ISOC_CHANNELS
,
227 &data
, sizeof(data
), 0);
233 release_resources(dg00x
);
237 int snd_dg00x_stream_init_duplex(struct snd_dg00x
*dg00x
)
241 /* For out-stream. */
242 err
= fw_iso_resources_init(&dg00x
->rx_resources
, dg00x
->unit
);
245 err
= amdtp_dot_init(&dg00x
->rx_stream
, dg00x
->unit
, AMDTP_OUT_STREAM
);
250 err
= fw_iso_resources_init(&dg00x
->tx_resources
, dg00x
->unit
);
253 err
= amdtp_dot_init(&dg00x
->tx_stream
, dg00x
->unit
, AMDTP_IN_STREAM
);
259 snd_dg00x_stream_destroy_duplex(dg00x
);
264 * This function should be called before starting streams or after stopping
267 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x
*dg00x
)
269 amdtp_stream_destroy(&dg00x
->rx_stream
);
270 fw_iso_resources_destroy(&dg00x
->rx_resources
);
272 amdtp_stream_destroy(&dg00x
->tx_stream
);
273 fw_iso_resources_destroy(&dg00x
->tx_resources
);
276 int snd_dg00x_stream_start_duplex(struct snd_dg00x
*dg00x
, unsigned int rate
)
278 unsigned int curr_rate
;
281 if (dg00x
->substreams_counter
== 0)
284 /* Check current sampling rate. */
285 err
= snd_dg00x_stream_get_local_rate(dg00x
, &curr_rate
);
290 if (curr_rate
!= rate
||
291 amdtp_streaming_error(&dg00x
->tx_stream
) ||
292 amdtp_streaming_error(&dg00x
->rx_stream
)) {
293 finish_session(dg00x
);
295 amdtp_stream_stop(&dg00x
->tx_stream
);
296 amdtp_stream_stop(&dg00x
->rx_stream
);
297 release_resources(dg00x
);
301 * No packets are transmitted without receiving packets, reagardless of
302 * which source of clock is used.
304 if (!amdtp_stream_running(&dg00x
->rx_stream
)) {
305 err
= snd_dg00x_stream_set_local_rate(dg00x
, rate
);
309 err
= keep_resources(dg00x
, rate
);
313 err
= begin_session(dg00x
);
317 err
= amdtp_stream_start(&dg00x
->rx_stream
,
318 dg00x
->rx_resources
.channel
,
319 fw_parent_device(dg00x
->unit
)->max_speed
);
323 if (!amdtp_stream_wait_callback(&dg00x
->rx_stream
,
331 * The value of SYT field in transmitted packets is always 0x0000. Thus,
332 * duplex streams with timestamp synchronization cannot be built.
334 if (!amdtp_stream_running(&dg00x
->tx_stream
)) {
335 err
= amdtp_stream_start(&dg00x
->tx_stream
,
336 dg00x
->tx_resources
.channel
,
337 fw_parent_device(dg00x
->unit
)->max_speed
);
341 if (!amdtp_stream_wait_callback(&dg00x
->tx_stream
,
350 finish_session(dg00x
);
352 amdtp_stream_stop(&dg00x
->tx_stream
);
353 amdtp_stream_stop(&dg00x
->rx_stream
);
354 release_resources(dg00x
);
359 void snd_dg00x_stream_stop_duplex(struct snd_dg00x
*dg00x
)
361 if (dg00x
->substreams_counter
> 0)
364 amdtp_stream_stop(&dg00x
->tx_stream
);
365 amdtp_stream_stop(&dg00x
->rx_stream
);
366 finish_session(dg00x
);
367 release_resources(dg00x
);
370 * Just after finishing the session, the device may lost transmitting
371 * functionality for a short time.
376 void snd_dg00x_stream_update_duplex(struct snd_dg00x
*dg00x
)
378 fw_iso_resources_update(&dg00x
->tx_resources
);
379 fw_iso_resources_update(&dg00x
->rx_resources
);
381 amdtp_stream_update(&dg00x
->tx_stream
);
382 amdtp_stream_update(&dg00x
->rx_stream
);
385 void snd_dg00x_stream_lock_changed(struct snd_dg00x
*dg00x
)
387 dg00x
->dev_lock_changed
= true;
388 wake_up(&dg00x
->hwdep_wait
);
391 int snd_dg00x_stream_lock_try(struct snd_dg00x
*dg00x
)
395 spin_lock_irq(&dg00x
->lock
);
397 /* user land lock this */
398 if (dg00x
->dev_lock_count
< 0) {
403 /* this is the first time */
404 if (dg00x
->dev_lock_count
++ == 0)
405 snd_dg00x_stream_lock_changed(dg00x
);
408 spin_unlock_irq(&dg00x
->lock
);
412 void snd_dg00x_stream_lock_release(struct snd_dg00x
*dg00x
)
414 spin_lock_irq(&dg00x
->lock
);
416 if (WARN_ON(dg00x
->dev_lock_count
<= 0))
418 if (--dg00x
->dev_lock_count
== 0)
419 snd_dg00x_stream_lock_changed(dg00x
);
421 spin_unlock_irq(&dg00x
->lock
);