1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
4 *
5 * Copyright (c) 2014-2015 Takashi Sakamoto
6 */
7
8 #include "digi00x.h"
9
10 #define READY_TIMEOUT_MS 200
11
12 const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = {
13 [SND_DG00X_RATE_44100] = 44100,
14 [SND_DG00X_RATE_48000] = 48000,
15 [SND_DG00X_RATE_88200] = 88200,
16 [SND_DG00X_RATE_96000] = 96000,
17 };
18
19 /* Multi Bit Linear Audio data channels for each sampling transfer frequency. */
20 const unsigned int
21 snd_dg00x_stream_pcm_channels[SND_DG00X_RATE_COUNT] = {
22 /* Analog/ADAT/SPDIF */
23 [SND_DG00X_RATE_44100] = (8 + 8 + 2),
24 [SND_DG00X_RATE_48000] = (8 + 8 + 2),
25 /* Analog/SPDIF */
26 [SND_DG00X_RATE_88200] = (8 + 2),
27 [SND_DG00X_RATE_96000] = (8 + 2),
28 };
29
snd_dg00x_stream_get_local_rate(struct snd_dg00x * dg00x,unsigned int * rate)30 int snd_dg00x_stream_get_local_rate(struct snd_dg00x *dg00x, unsigned int *rate)
31 {
32 u32 data;
33 __be32 reg;
34 int err;
35
36 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
37 DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
38 ®, sizeof(reg), 0);
39 if (err < 0)
40 return err;
41
42 data = be32_to_cpu(reg) & 0x0f;
43 if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
44 *rate = snd_dg00x_stream_rates[data];
45 else
46 err = -EIO;
47
48 return err;
49 }
50
snd_dg00x_stream_set_local_rate(struct snd_dg00x * dg00x,unsigned int rate)51 int snd_dg00x_stream_set_local_rate(struct snd_dg00x *dg00x, unsigned int rate)
52 {
53 __be32 reg;
54 unsigned int i;
55
56 for (i = 0; i < ARRAY_SIZE(snd_dg00x_stream_rates); i++) {
57 if (rate == snd_dg00x_stream_rates[i])
58 break;
59 }
60 if (i == ARRAY_SIZE(snd_dg00x_stream_rates))
61 return -EINVAL;
62
63 reg = cpu_to_be32(i);
64 return snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
65 DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
66 ®, sizeof(reg), 0);
67 }
68
snd_dg00x_stream_get_clock(struct snd_dg00x * dg00x,enum snd_dg00x_clock * clock)69 int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x,
70 enum snd_dg00x_clock *clock)
71 {
72 __be32 reg;
73 int err;
74
75 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
76 DG00X_ADDR_BASE + DG00X_OFFSET_CLOCK_SOURCE,
77 ®, sizeof(reg), 0);
78 if (err < 0)
79 return err;
80
81 *clock = be32_to_cpu(reg) & 0x0f;
82 if (*clock >= SND_DG00X_CLOCK_COUNT)
83 err = -EIO;
84
85 return err;
86 }
87
snd_dg00x_stream_check_external_clock(struct snd_dg00x * dg00x,bool * detect)88 int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect)
89 {
90 __be32 reg;
91 int err;
92
93 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
94 DG00X_ADDR_BASE + DG00X_OFFSET_DETECT_EXTERNAL,
95 ®, sizeof(reg), 0);
96 if (err >= 0)
97 *detect = be32_to_cpu(reg) > 0;
98
99 return err;
100 }
101
snd_dg00x_stream_get_external_rate(struct snd_dg00x * dg00x,unsigned int * rate)102 int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x,
103 unsigned int *rate)
104 {
105 u32 data;
106 __be32 reg;
107 int err;
108
109 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
110 DG00X_ADDR_BASE + DG00X_OFFSET_EXTERNAL_RATE,
111 ®, sizeof(reg), 0);
112 if (err < 0)
113 return err;
114
115 data = be32_to_cpu(reg) & 0x0f;
116 if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
117 *rate = snd_dg00x_stream_rates[data];
118 /* This means desync. */
119 else
120 err = -EBUSY;
121
122 return err;
123 }
124
finish_session(struct snd_dg00x * dg00x)125 static void finish_session(struct snd_dg00x *dg00x)
126 {
127 __be32 data;
128
129 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);
133
134 // Unregister isochronous channels for both direction.
135 data = 0;
136 snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
137 DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
138 &data, sizeof(data), 0);
139
140 // Just after finishing the session, the device may lost transmitting
141 // functionality for a short time.
142 msleep(50);
143 }
144
begin_session(struct snd_dg00x * dg00x)145 static int begin_session(struct snd_dg00x *dg00x)
146 {
147 __be32 data;
148 u32 curr;
149 int err;
150
151 // Register isochronous channels for both direction.
152 data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
153 dg00x->rx_resources.channel);
154 err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
155 DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
156 &data, sizeof(data), 0);
157 if (err < 0)
158 return err;
159
160 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
161 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE,
162 &data, sizeof(data), 0);
163 if (err < 0)
164 return err;
165 curr = be32_to_cpu(data);
166
167 if (curr == 0)
168 curr = 2;
169
170 curr--;
171 while (curr > 0) {
172 data = cpu_to_be32(curr);
173 err = snd_fw_transaction(dg00x->unit,
174 TCODE_WRITE_QUADLET_REQUEST,
175 DG00X_ADDR_BASE +
176 DG00X_OFFSET_STREAMING_SET,
177 &data, sizeof(data), 0);
178 if (err < 0)
179 break;
180
181 msleep(20);
182 curr--;
183 }
184
185 return err;
186 }
187
keep_resources(struct snd_dg00x * dg00x,struct amdtp_stream * stream,unsigned int rate)188 static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
189 unsigned int rate)
190 {
191 struct fw_iso_resources *resources;
192 int i;
193 int err;
194
195 // Check sampling rate.
196 for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
197 if (snd_dg00x_stream_rates[i] == rate)
198 break;
199 }
200 if (i == SND_DG00X_RATE_COUNT)
201 return -EINVAL;
202
203 if (stream == &dg00x->tx_stream)
204 resources = &dg00x->tx_resources;
205 else
206 resources = &dg00x->rx_resources;
207
208 err = amdtp_dot_set_parameters(stream, rate,
209 snd_dg00x_stream_pcm_channels[i]);
210 if (err < 0)
211 return err;
212
213 return fw_iso_resources_allocate(resources,
214 amdtp_stream_get_max_payload(stream),
215 fw_parent_device(dg00x->unit)->max_speed);
216 }
217
init_stream(struct snd_dg00x * dg00x,struct amdtp_stream * s)218 static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
219 {
220 struct fw_iso_resources *resources;
221 enum amdtp_stream_direction dir;
222 int err;
223
224 if (s == &dg00x->tx_stream) {
225 resources = &dg00x->tx_resources;
226 dir = AMDTP_IN_STREAM;
227 } else {
228 resources = &dg00x->rx_resources;
229 dir = AMDTP_OUT_STREAM;
230 }
231
232 err = fw_iso_resources_init(resources, dg00x->unit);
233 if (err < 0)
234 return err;
235
236 err = amdtp_dot_init(s, dg00x->unit, dir);
237 if (err < 0)
238 fw_iso_resources_destroy(resources);
239
240 return err;
241 }
242
destroy_stream(struct snd_dg00x * dg00x,struct amdtp_stream * s)243 static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
244 {
245 amdtp_stream_destroy(s);
246
247 if (s == &dg00x->tx_stream)
248 fw_iso_resources_destroy(&dg00x->tx_resources);
249 else
250 fw_iso_resources_destroy(&dg00x->rx_resources);
251 }
252
snd_dg00x_stream_init_duplex(struct snd_dg00x * dg00x)253 int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
254 {
255 int err;
256
257 err = init_stream(dg00x, &dg00x->rx_stream);
258 if (err < 0)
259 return err;
260
261 err = init_stream(dg00x, &dg00x->tx_stream);
262 if (err < 0) {
263 destroy_stream(dg00x, &dg00x->rx_stream);
264 return err;
265 }
266
267 err = amdtp_domain_init(&dg00x->domain);
268 if (err < 0) {
269 destroy_stream(dg00x, &dg00x->rx_stream);
270 destroy_stream(dg00x, &dg00x->tx_stream);
271 }
272
273 return err;
274 }
275
276 /*
277 * This function should be called before starting streams or after stopping
278 * streams.
279 */
snd_dg00x_stream_destroy_duplex(struct snd_dg00x * dg00x)280 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
281 {
282 amdtp_domain_destroy(&dg00x->domain);
283
284 destroy_stream(dg00x, &dg00x->rx_stream);
285 destroy_stream(dg00x, &dg00x->tx_stream);
286 }
287
snd_dg00x_stream_reserve_duplex(struct snd_dg00x * dg00x,unsigned int rate,unsigned int frames_per_period,unsigned int frames_per_buffer)288 int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
289 unsigned int frames_per_period,
290 unsigned int frames_per_buffer)
291 {
292 unsigned int curr_rate;
293 int err;
294
295 err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
296 if (err < 0)
297 return err;
298 if (rate == 0)
299 rate = curr_rate;
300
301 if (dg00x->substreams_counter == 0 || curr_rate != rate) {
302 amdtp_domain_stop(&dg00x->domain);
303
304 finish_session(dg00x);
305
306 fw_iso_resources_free(&dg00x->tx_resources);
307 fw_iso_resources_free(&dg00x->rx_resources);
308
309 err = snd_dg00x_stream_set_local_rate(dg00x, rate);
310 if (err < 0)
311 return err;
312
313 err = keep_resources(dg00x, &dg00x->rx_stream, rate);
314 if (err < 0)
315 return err;
316
317 err = keep_resources(dg00x, &dg00x->tx_stream, rate);
318 if (err < 0) {
319 fw_iso_resources_free(&dg00x->rx_resources);
320 return err;
321 }
322
323 err = amdtp_domain_set_events_per_period(&dg00x->domain,
324 frames_per_period, frames_per_buffer);
325 if (err < 0) {
326 fw_iso_resources_free(&dg00x->rx_resources);
327 fw_iso_resources_free(&dg00x->tx_resources);
328 return err;
329 }
330 }
331
332 return 0;
333 }
334
snd_dg00x_stream_start_duplex(struct snd_dg00x * dg00x)335 int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
336 {
337 unsigned int generation = dg00x->rx_resources.generation;
338 int err = 0;
339
340 if (dg00x->substreams_counter == 0)
341 return 0;
342
343 if (amdtp_streaming_error(&dg00x->tx_stream) ||
344 amdtp_streaming_error(&dg00x->rx_stream)) {
345 amdtp_domain_stop(&dg00x->domain);
346 finish_session(dg00x);
347 }
348
349 if (generation != fw_parent_device(dg00x->unit)->card->generation) {
350 err = fw_iso_resources_update(&dg00x->tx_resources);
351 if (err < 0)
352 goto error;
353
354 err = fw_iso_resources_update(&dg00x->rx_resources);
355 if (err < 0)
356 goto error;
357 }
358
359 /*
360 * No packets are transmitted without receiving packets, reagardless of
361 * which source of clock is used.
362 */
363 if (!amdtp_stream_running(&dg00x->rx_stream)) {
364 int spd = fw_parent_device(dg00x->unit)->max_speed;
365
366 err = begin_session(dg00x);
367 if (err < 0)
368 goto error;
369
370 err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
371 dg00x->rx_resources.channel, spd);
372 if (err < 0)
373 goto error;
374
375 err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
376 dg00x->tx_resources.channel, spd);
377 if (err < 0)
378 goto error;
379
380 // NOTE: The device doesn't start packet transmission till receiving any packet.
381 // It ignores presentation time expressed by the value of syt field of CIP header
382 // in received packets. The sequence of the number of data blocks per packet is
383 // important for media clock recovery.
384 err = amdtp_domain_start(&dg00x->domain, 0, true, true);
385 if (err < 0)
386 goto error;
387
388 if (!amdtp_domain_wait_ready(&dg00x->domain, READY_TIMEOUT_MS)) {
389 err = -ETIMEDOUT;
390 goto error;
391 }
392 }
393
394 return 0;
395 error:
396 amdtp_domain_stop(&dg00x->domain);
397 finish_session(dg00x);
398
399 return err;
400 }
401
snd_dg00x_stream_stop_duplex(struct snd_dg00x * dg00x)402 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
403 {
404 if (dg00x->substreams_counter == 0) {
405 amdtp_domain_stop(&dg00x->domain);
406 finish_session(dg00x);
407
408 fw_iso_resources_free(&dg00x->tx_resources);
409 fw_iso_resources_free(&dg00x->rx_resources);
410 }
411 }
412
snd_dg00x_stream_update_duplex(struct snd_dg00x * dg00x)413 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)
414 {
415 fw_iso_resources_update(&dg00x->tx_resources);
416 fw_iso_resources_update(&dg00x->rx_resources);
417
418 amdtp_stream_update(&dg00x->tx_stream);
419 amdtp_stream_update(&dg00x->rx_stream);
420 }
421
snd_dg00x_stream_lock_changed(struct snd_dg00x * dg00x)422 void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x)
423 {
424 dg00x->dev_lock_changed = true;
425 wake_up(&dg00x->hwdep_wait);
426 }
427
snd_dg00x_stream_lock_try(struct snd_dg00x * dg00x)428 int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x)
429 {
430 int err;
431
432 spin_lock_irq(&dg00x->lock);
433
434 /* user land lock this */
435 if (dg00x->dev_lock_count < 0) {
436 err = -EBUSY;
437 goto end;
438 }
439
440 /* this is the first time */
441 if (dg00x->dev_lock_count++ == 0)
442 snd_dg00x_stream_lock_changed(dg00x);
443 err = 0;
444 end:
445 spin_unlock_irq(&dg00x->lock);
446 return err;
447 }
448
snd_dg00x_stream_lock_release(struct snd_dg00x * dg00x)449 void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x)
450 {
451 spin_lock_irq(&dg00x->lock);
452
453 if (WARN_ON(dg00x->dev_lock_count <= 0))
454 goto end;
455 if (--dg00x->dev_lock_count == 0)
456 snd_dg00x_stream_lock_changed(dg00x);
457 end:
458 spin_unlock_irq(&dg00x->lock);
459 }
460