Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/dice/dice-stream.c
26442 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* dice_stream.c - a part of driver for DICE based devices
4
*
5
* Copyright (c) Clemens Ladisch <[email protected]>
6
* Copyright (c) 2014 Takashi Sakamoto <[email protected]>
7
*/
8
9
#include "dice.h"
10
11
#define READY_TIMEOUT_MS 200
12
#define NOTIFICATION_TIMEOUT_MS 100
13
14
struct reg_params {
15
unsigned int count;
16
unsigned int size;
17
};
18
19
const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
20
/* mode 0 */
21
[0] = 32000,
22
[1] = 44100,
23
[2] = 48000,
24
/* mode 1 */
25
[3] = 88200,
26
[4] = 96000,
27
/* mode 2 */
28
[5] = 176400,
29
[6] = 192000,
30
};
31
32
int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
33
enum snd_dice_rate_mode *mode)
34
{
35
/* Corresponding to each entry in snd_dice_rates. */
36
static const enum snd_dice_rate_mode modes[] = {
37
[0] = SND_DICE_RATE_MODE_LOW,
38
[1] = SND_DICE_RATE_MODE_LOW,
39
[2] = SND_DICE_RATE_MODE_LOW,
40
[3] = SND_DICE_RATE_MODE_MIDDLE,
41
[4] = SND_DICE_RATE_MODE_MIDDLE,
42
[5] = SND_DICE_RATE_MODE_HIGH,
43
[6] = SND_DICE_RATE_MODE_HIGH,
44
};
45
int i;
46
47
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
48
if (!(dice->clock_caps & BIT(i)))
49
continue;
50
if (snd_dice_rates[i] != rate)
51
continue;
52
53
*mode = modes[i];
54
return 0;
55
}
56
57
return -EINVAL;
58
}
59
60
static int select_clock(struct snd_dice *dice, unsigned int rate)
61
{
62
__be32 reg, new;
63
u32 data;
64
int i;
65
int err;
66
67
err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
68
&reg, sizeof(reg));
69
if (err < 0)
70
return err;
71
72
data = be32_to_cpu(reg);
73
74
data &= ~CLOCK_RATE_MASK;
75
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
76
if (snd_dice_rates[i] == rate)
77
break;
78
}
79
if (i == ARRAY_SIZE(snd_dice_rates))
80
return -EINVAL;
81
data |= i << CLOCK_RATE_SHIFT;
82
83
if (completion_done(&dice->clock_accepted))
84
reinit_completion(&dice->clock_accepted);
85
86
new = cpu_to_be32(data);
87
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
88
&new, sizeof(new));
89
if (err < 0)
90
return err;
91
92
if (wait_for_completion_timeout(&dice->clock_accepted,
93
msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
94
if (reg != new)
95
return -ETIMEDOUT;
96
}
97
98
return 0;
99
}
100
101
static int get_register_params(struct snd_dice *dice,
102
struct reg_params *tx_params,
103
struct reg_params *rx_params)
104
{
105
__be32 reg[2];
106
int err;
107
108
err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
109
if (err < 0)
110
return err;
111
tx_params->count =
112
min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
113
tx_params->size = be32_to_cpu(reg[1]) * 4;
114
115
err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
116
if (err < 0)
117
return err;
118
rx_params->count =
119
min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
120
rx_params->size = be32_to_cpu(reg[1]) * 4;
121
122
return 0;
123
}
124
125
static void release_resources(struct snd_dice *dice)
126
{
127
int i;
128
129
for (i = 0; i < MAX_STREAMS; ++i) {
130
fw_iso_resources_free(&dice->tx_resources[i]);
131
fw_iso_resources_free(&dice->rx_resources[i]);
132
}
133
}
134
135
static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
136
struct reg_params *params)
137
{
138
__be32 reg;
139
unsigned int i;
140
141
for (i = 0; i < params->count; i++) {
142
reg = cpu_to_be32((u32)-1);
143
if (dir == AMDTP_IN_STREAM) {
144
snd_dice_transaction_write_tx(dice,
145
params->size * i + TX_ISOCHRONOUS,
146
&reg, sizeof(reg));
147
} else {
148
snd_dice_transaction_write_rx(dice,
149
params->size * i + RX_ISOCHRONOUS,
150
&reg, sizeof(reg));
151
}
152
}
153
}
154
155
static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
156
struct fw_iso_resources *resources, unsigned int rate,
157
unsigned int pcm_chs, unsigned int midi_ports)
158
{
159
bool double_pcm_frames;
160
unsigned int i;
161
int err;
162
163
// At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
164
// one data block of AMDTP packet. Thus sampling transfer frequency is
165
// a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
166
// transferred on AMDTP packets at 96 kHz. Two successive samples of a
167
// channel are stored consecutively in the packet. This quirk is called
168
// as 'Dual Wire'.
169
// For this quirk, blocking mode is required and PCM buffer size should
170
// be aligned to SYT_INTERVAL.
171
double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
172
if (double_pcm_frames) {
173
rate /= 2;
174
pcm_chs *= 2;
175
}
176
177
err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
178
double_pcm_frames);
179
if (err < 0)
180
return err;
181
182
if (double_pcm_frames) {
183
pcm_chs /= 2;
184
185
for (i = 0; i < pcm_chs; i++) {
186
amdtp_am824_set_pcm_position(stream, i, i * 2);
187
amdtp_am824_set_pcm_position(stream, i + pcm_chs,
188
i * 2 + 1);
189
}
190
}
191
192
return fw_iso_resources_allocate(resources,
193
amdtp_stream_get_max_payload(stream),
194
fw_parent_device(dice->unit)->max_speed);
195
}
196
197
static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
198
enum amdtp_stream_direction dir,
199
struct reg_params *params)
200
{
201
enum snd_dice_rate_mode mode;
202
int i;
203
int err;
204
205
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
206
if (err < 0)
207
return err;
208
209
for (i = 0; i < params->count; ++i) {
210
__be32 reg[2];
211
struct amdtp_stream *stream;
212
struct fw_iso_resources *resources;
213
unsigned int pcm_cache;
214
unsigned int pcm_chs;
215
unsigned int midi_ports;
216
217
if (dir == AMDTP_IN_STREAM) {
218
stream = &dice->tx_stream[i];
219
resources = &dice->tx_resources[i];
220
221
pcm_cache = dice->tx_pcm_chs[i][mode];
222
err = snd_dice_transaction_read_tx(dice,
223
params->size * i + TX_NUMBER_AUDIO,
224
reg, sizeof(reg));
225
} else {
226
stream = &dice->rx_stream[i];
227
resources = &dice->rx_resources[i];
228
229
pcm_cache = dice->rx_pcm_chs[i][mode];
230
err = snd_dice_transaction_read_rx(dice,
231
params->size * i + RX_NUMBER_AUDIO,
232
reg, sizeof(reg));
233
}
234
if (err < 0)
235
return err;
236
pcm_chs = be32_to_cpu(reg[0]);
237
midi_ports = be32_to_cpu(reg[1]);
238
239
// These are important for developer of this driver.
240
if (pcm_chs != pcm_cache) {
241
dev_info(&dice->unit->device,
242
"cache mismatch: pcm: %u:%u, midi: %u\n",
243
pcm_chs, pcm_cache, midi_ports);
244
return -EPROTO;
245
}
246
247
err = keep_resources(dice, stream, resources, rate, pcm_chs,
248
midi_ports);
249
if (err < 0)
250
return err;
251
}
252
253
return 0;
254
}
255
256
static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
257
struct reg_params *rx_params)
258
{
259
stop_streams(dice, AMDTP_IN_STREAM, tx_params);
260
stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
261
262
snd_dice_transaction_clear_enable(dice);
263
}
264
265
int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
266
unsigned int events_per_period,
267
unsigned int events_per_buffer)
268
{
269
unsigned int curr_rate;
270
int err;
271
272
// Check sampling transmission frequency.
273
err = snd_dice_transaction_get_rate(dice, &curr_rate);
274
if (err < 0)
275
return err;
276
if (rate == 0)
277
rate = curr_rate;
278
279
if (dice->substreams_counter == 0 || curr_rate != rate) {
280
struct reg_params tx_params, rx_params;
281
282
amdtp_domain_stop(&dice->domain);
283
284
err = get_register_params(dice, &tx_params, &rx_params);
285
if (err < 0)
286
return err;
287
finish_session(dice, &tx_params, &rx_params);
288
289
release_resources(dice);
290
291
// Just after owning the unit (GLOBAL_OWNER), the unit can
292
// return invalid stream formats. Selecting clock parameters
293
// have an effect for the unit to refine it.
294
err = select_clock(dice, rate);
295
if (err < 0)
296
return err;
297
298
// After changing sampling transfer frequency, the value of
299
// register can be changed.
300
err = get_register_params(dice, &tx_params, &rx_params);
301
if (err < 0)
302
return err;
303
304
err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
305
&tx_params);
306
if (err < 0)
307
goto error;
308
309
err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
310
&rx_params);
311
if (err < 0)
312
goto error;
313
314
err = amdtp_domain_set_events_per_period(&dice->domain,
315
events_per_period, events_per_buffer);
316
if (err < 0)
317
goto error;
318
}
319
320
return 0;
321
error:
322
release_resources(dice);
323
return err;
324
}
325
326
static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
327
unsigned int rate, struct reg_params *params)
328
{
329
unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
330
int i;
331
int err;
332
333
for (i = 0; i < params->count; i++) {
334
struct amdtp_stream *stream;
335
struct fw_iso_resources *resources;
336
__be32 reg;
337
338
if (dir == AMDTP_IN_STREAM) {
339
stream = dice->tx_stream + i;
340
resources = dice->tx_resources + i;
341
} else {
342
stream = dice->rx_stream + i;
343
resources = dice->rx_resources + i;
344
}
345
346
reg = cpu_to_be32(resources->channel);
347
if (dir == AMDTP_IN_STREAM) {
348
err = snd_dice_transaction_write_tx(dice,
349
params->size * i + TX_ISOCHRONOUS,
350
&reg, sizeof(reg));
351
} else {
352
err = snd_dice_transaction_write_rx(dice,
353
params->size * i + RX_ISOCHRONOUS,
354
&reg, sizeof(reg));
355
}
356
if (err < 0)
357
return err;
358
359
if (dir == AMDTP_IN_STREAM) {
360
reg = cpu_to_be32(max_speed);
361
err = snd_dice_transaction_write_tx(dice,
362
params->size * i + TX_SPEED,
363
&reg, sizeof(reg));
364
if (err < 0)
365
return err;
366
}
367
368
err = amdtp_domain_add_stream(&dice->domain, stream,
369
resources->channel, max_speed);
370
if (err < 0)
371
return err;
372
}
373
374
return 0;
375
}
376
377
/*
378
* MEMO: After this function, there're two states of streams:
379
* - None streams are running.
380
* - All streams are running.
381
*/
382
int snd_dice_stream_start_duplex(struct snd_dice *dice)
383
{
384
unsigned int generation = dice->rx_resources[0].generation;
385
struct reg_params tx_params, rx_params;
386
unsigned int i;
387
unsigned int rate;
388
enum snd_dice_rate_mode mode;
389
int err;
390
391
if (dice->substreams_counter == 0)
392
return -EIO;
393
394
err = get_register_params(dice, &tx_params, &rx_params);
395
if (err < 0)
396
return err;
397
398
// Check error of packet streaming.
399
for (i = 0; i < MAX_STREAMS; ++i) {
400
if (amdtp_streaming_error(&dice->tx_stream[i]) ||
401
amdtp_streaming_error(&dice->rx_stream[i])) {
402
amdtp_domain_stop(&dice->domain);
403
finish_session(dice, &tx_params, &rx_params);
404
break;
405
}
406
}
407
408
if (generation != fw_parent_device(dice->unit)->card->generation) {
409
for (i = 0; i < MAX_STREAMS; ++i) {
410
if (i < tx_params.count)
411
fw_iso_resources_update(dice->tx_resources + i);
412
if (i < rx_params.count)
413
fw_iso_resources_update(dice->rx_resources + i);
414
}
415
}
416
417
// Check required streams are running or not.
418
err = snd_dice_transaction_get_rate(dice, &rate);
419
if (err < 0)
420
return err;
421
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
422
if (err < 0)
423
return err;
424
for (i = 0; i < MAX_STREAMS; ++i) {
425
if (dice->tx_pcm_chs[i][mode] > 0 &&
426
!amdtp_stream_running(&dice->tx_stream[i]))
427
break;
428
if (dice->rx_pcm_chs[i][mode] > 0 &&
429
!amdtp_stream_running(&dice->rx_stream[i]))
430
break;
431
}
432
if (i < MAX_STREAMS) {
433
// Start both streams.
434
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
435
if (err < 0)
436
goto error;
437
438
err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
439
if (err < 0)
440
goto error;
441
442
err = snd_dice_transaction_set_enable(dice);
443
if (err < 0) {
444
dev_err(&dice->unit->device,
445
"fail to enable interface\n");
446
goto error;
447
}
448
449
// MEMO: The device immediately starts packet transmission when enabled. Some
450
// devices are strictly to generate any discontinuity in the sequence of tx packet
451
// when they receives invalid sequence of presentation time in CIP header. The
452
// sequence replay for media clock recovery can suppress the behaviour.
453
err = amdtp_domain_start(&dice->domain, 0, true, false);
454
if (err < 0)
455
goto error;
456
457
if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
458
err = -ETIMEDOUT;
459
goto error;
460
}
461
}
462
463
return 0;
464
error:
465
amdtp_domain_stop(&dice->domain);
466
finish_session(dice, &tx_params, &rx_params);
467
return err;
468
}
469
470
/*
471
* MEMO: After this function, there're two states of streams:
472
* - None streams are running.
473
* - All streams are running.
474
*/
475
void snd_dice_stream_stop_duplex(struct snd_dice *dice)
476
{
477
struct reg_params tx_params, rx_params;
478
479
if (dice->substreams_counter == 0) {
480
if (get_register_params(dice, &tx_params, &rx_params) >= 0)
481
finish_session(dice, &tx_params, &rx_params);
482
483
amdtp_domain_stop(&dice->domain);
484
release_resources(dice);
485
}
486
}
487
488
static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
489
unsigned int index)
490
{
491
struct amdtp_stream *stream;
492
struct fw_iso_resources *resources;
493
int err;
494
495
if (dir == AMDTP_IN_STREAM) {
496
stream = &dice->tx_stream[index];
497
resources = &dice->tx_resources[index];
498
} else {
499
stream = &dice->rx_stream[index];
500
resources = &dice->rx_resources[index];
501
}
502
503
err = fw_iso_resources_init(resources, dice->unit);
504
if (err < 0)
505
goto end;
506
resources->channels_mask = 0x00000000ffffffffuLL;
507
508
err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
509
if (err < 0) {
510
amdtp_stream_destroy(stream);
511
fw_iso_resources_destroy(resources);
512
}
513
end:
514
return err;
515
}
516
517
/*
518
* This function should be called before starting streams or after stopping
519
* streams.
520
*/
521
static void destroy_stream(struct snd_dice *dice,
522
enum amdtp_stream_direction dir,
523
unsigned int index)
524
{
525
struct amdtp_stream *stream;
526
struct fw_iso_resources *resources;
527
528
if (dir == AMDTP_IN_STREAM) {
529
stream = &dice->tx_stream[index];
530
resources = &dice->tx_resources[index];
531
} else {
532
stream = &dice->rx_stream[index];
533
resources = &dice->rx_resources[index];
534
}
535
536
amdtp_stream_destroy(stream);
537
fw_iso_resources_destroy(resources);
538
}
539
540
int snd_dice_stream_init_duplex(struct snd_dice *dice)
541
{
542
int i, err;
543
544
for (i = 0; i < MAX_STREAMS; i++) {
545
err = init_stream(dice, AMDTP_IN_STREAM, i);
546
if (err < 0) {
547
for (; i >= 0; i--)
548
destroy_stream(dice, AMDTP_IN_STREAM, i);
549
goto end;
550
}
551
}
552
553
for (i = 0; i < MAX_STREAMS; i++) {
554
err = init_stream(dice, AMDTP_OUT_STREAM, i);
555
if (err < 0) {
556
for (; i >= 0; i--)
557
destroy_stream(dice, AMDTP_OUT_STREAM, i);
558
for (i = 0; i < MAX_STREAMS; i++)
559
destroy_stream(dice, AMDTP_IN_STREAM, i);
560
goto end;
561
}
562
}
563
564
err = amdtp_domain_init(&dice->domain);
565
if (err < 0) {
566
for (i = 0; i < MAX_STREAMS; ++i) {
567
destroy_stream(dice, AMDTP_OUT_STREAM, i);
568
destroy_stream(dice, AMDTP_IN_STREAM, i);
569
}
570
}
571
end:
572
return err;
573
}
574
575
void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
576
{
577
unsigned int i;
578
579
for (i = 0; i < MAX_STREAMS; i++) {
580
destroy_stream(dice, AMDTP_IN_STREAM, i);
581
destroy_stream(dice, AMDTP_OUT_STREAM, i);
582
}
583
584
amdtp_domain_destroy(&dice->domain);
585
}
586
587
void snd_dice_stream_update_duplex(struct snd_dice *dice)
588
{
589
struct reg_params tx_params, rx_params;
590
591
/*
592
* On a bus reset, the DICE firmware disables streaming and then goes
593
* off contemplating its own navel for hundreds of milliseconds before
594
* it can react to any of our attempts to reenable streaming. This
595
* means that we lose synchronization anyway, so we force our streams
596
* to stop so that the application can restart them in an orderly
597
* manner.
598
*/
599
dice->global_enabled = false;
600
601
if (get_register_params(dice, &tx_params, &rx_params) == 0) {
602
amdtp_domain_stop(&dice->domain);
603
604
stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
605
stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
606
}
607
}
608
609
int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
610
{
611
unsigned int rate;
612
enum snd_dice_rate_mode mode;
613
__be32 reg[2];
614
struct reg_params tx_params, rx_params;
615
int i;
616
int err;
617
618
/* If extended protocol is available, detect detail spec. */
619
err = snd_dice_detect_extension_formats(dice);
620
if (err >= 0)
621
return err;
622
623
/*
624
* Available stream format is restricted at current mode of sampling
625
* clock.
626
*/
627
err = snd_dice_transaction_get_rate(dice, &rate);
628
if (err < 0)
629
return err;
630
631
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
632
if (err < 0)
633
return err;
634
635
/*
636
* Just after owning the unit (GLOBAL_OWNER), the unit can return
637
* invalid stream formats. Selecting clock parameters have an effect
638
* for the unit to refine it.
639
*/
640
err = select_clock(dice, rate);
641
if (err < 0)
642
return err;
643
644
err = get_register_params(dice, &tx_params, &rx_params);
645
if (err < 0)
646
return err;
647
648
for (i = 0; i < tx_params.count; ++i) {
649
err = snd_dice_transaction_read_tx(dice,
650
tx_params.size * i + TX_NUMBER_AUDIO,
651
reg, sizeof(reg));
652
if (err < 0)
653
return err;
654
dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
655
dice->tx_midi_ports[i] = max_t(unsigned int,
656
be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
657
}
658
for (i = 0; i < rx_params.count; ++i) {
659
err = snd_dice_transaction_read_rx(dice,
660
rx_params.size * i + RX_NUMBER_AUDIO,
661
reg, sizeof(reg));
662
if (err < 0)
663
return err;
664
dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
665
dice->rx_midi_ports[i] = max_t(unsigned int,
666
be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
667
}
668
669
return 0;
670
}
671
672
static void dice_lock_changed(struct snd_dice *dice)
673
{
674
dice->dev_lock_changed = true;
675
wake_up(&dice->hwdep_wait);
676
}
677
678
int snd_dice_stream_lock_try(struct snd_dice *dice)
679
{
680
int err;
681
682
spin_lock_irq(&dice->lock);
683
684
if (dice->dev_lock_count < 0) {
685
err = -EBUSY;
686
goto out;
687
}
688
689
if (dice->dev_lock_count++ == 0)
690
dice_lock_changed(dice);
691
err = 0;
692
out:
693
spin_unlock_irq(&dice->lock);
694
return err;
695
}
696
697
void snd_dice_stream_lock_release(struct snd_dice *dice)
698
{
699
spin_lock_irq(&dice->lock);
700
701
if (WARN_ON(dice->dev_lock_count <= 0))
702
goto out;
703
704
if (--dice->dev_lock_count == 0)
705
dice_lock_changed(dice);
706
out:
707
spin_unlock_irq(&dice->lock);
708
}
709
710