1
2
3
4
5
6
7
8
9
10#include "dice.h"
11
12#define CALLBACK_TIMEOUT 200
13#define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
14
15struct reg_params {
16 unsigned int count;
17 unsigned int size;
18};
19
20const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
21
22 [0] = 32000,
23 [1] = 44100,
24 [2] = 48000,
25
26 [3] = 88200,
27 [4] = 96000,
28
29 [5] = 176400,
30 [6] = 192000,
31};
32
33
34
35
36
37static int ensure_phase_lock(struct snd_dice *dice)
38{
39 __be32 reg, nominal;
40 int err;
41
42 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
43 ®, sizeof(reg));
44 if (err < 0)
45 return err;
46
47 if (completion_done(&dice->clock_accepted))
48 reinit_completion(&dice->clock_accepted);
49
50 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
51 ®, sizeof(reg));
52 if (err < 0)
53 return err;
54
55 if (wait_for_completion_timeout(&dice->clock_accepted,
56 msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
57
58
59
60
61
62 err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS,
63 &nominal, sizeof(nominal));
64 if (err < 0)
65 return err;
66 if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED))
67 return -ETIMEDOUT;
68 }
69
70 return 0;
71}
72
73static int get_register_params(struct snd_dice *dice,
74 struct reg_params *tx_params,
75 struct reg_params *rx_params)
76{
77 __be32 reg[2];
78 int err;
79
80 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
81 if (err < 0)
82 return err;
83 tx_params->count =
84 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
85 tx_params->size = be32_to_cpu(reg[1]) * 4;
86
87 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
88 if (err < 0)
89 return err;
90 rx_params->count =
91 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
92 rx_params->size = be32_to_cpu(reg[1]) * 4;
93
94 return 0;
95}
96
97static void release_resources(struct snd_dice *dice)
98{
99 unsigned int i;
100
101 for (i = 0; i < MAX_STREAMS; i++) {
102 if (amdtp_stream_running(&dice->tx_stream[i])) {
103 amdtp_stream_pcm_abort(&dice->tx_stream[i]);
104 amdtp_stream_stop(&dice->tx_stream[i]);
105 }
106 if (amdtp_stream_running(&dice->rx_stream[i])) {
107 amdtp_stream_pcm_abort(&dice->rx_stream[i]);
108 amdtp_stream_stop(&dice->rx_stream[i]);
109 }
110
111 fw_iso_resources_free(&dice->tx_resources[i]);
112 fw_iso_resources_free(&dice->rx_resources[i]);
113 }
114}
115
116static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
117 struct reg_params *params)
118{
119 __be32 reg;
120 unsigned int i;
121
122 for (i = 0; i < params->count; i++) {
123 reg = cpu_to_be32((u32)-1);
124 if (dir == AMDTP_IN_STREAM) {
125 snd_dice_transaction_write_tx(dice,
126 params->size * i + TX_ISOCHRONOUS,
127 ®, sizeof(reg));
128 } else {
129 snd_dice_transaction_write_rx(dice,
130 params->size * i + RX_ISOCHRONOUS,
131 ®, sizeof(reg));
132 }
133 }
134}
135
136static int keep_resources(struct snd_dice *dice,
137 enum amdtp_stream_direction dir, unsigned int index,
138 unsigned int rate, unsigned int pcm_chs,
139 unsigned int midi_ports)
140{
141 struct amdtp_stream *stream;
142 struct fw_iso_resources *resources;
143 bool double_pcm_frames;
144 unsigned int i;
145 int err;
146
147 if (dir == AMDTP_IN_STREAM) {
148 stream = &dice->tx_stream[index];
149 resources = &dice->tx_resources[index];
150 } else {
151 stream = &dice->rx_stream[index];
152 resources = &dice->rx_resources[index];
153 }
154
155
156
157
158
159
160
161
162
163
164
165 double_pcm_frames = rate > 96000;
166 if (double_pcm_frames) {
167 rate /= 2;
168 pcm_chs *= 2;
169 }
170
171 err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
172 double_pcm_frames);
173 if (err < 0)
174 return err;
175
176 if (double_pcm_frames) {
177 pcm_chs /= 2;
178
179 for (i = 0; i < pcm_chs; i++) {
180 amdtp_am824_set_pcm_position(stream, i, i * 2);
181 amdtp_am824_set_pcm_position(stream, i + pcm_chs,
182 i * 2 + 1);
183 }
184 }
185
186 return fw_iso_resources_allocate(resources,
187 amdtp_stream_get_max_payload(stream),
188 fw_parent_device(dice->unit)->max_speed);
189}
190
191static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
192 unsigned int rate, struct reg_params *params)
193{
194 __be32 reg[2];
195 unsigned int i, pcm_chs, midi_ports;
196 struct amdtp_stream *streams;
197 struct fw_iso_resources *resources;
198 struct fw_device *fw_dev = fw_parent_device(dice->unit);
199 int err = 0;
200
201 if (dir == AMDTP_IN_STREAM) {
202 streams = dice->tx_stream;
203 resources = dice->tx_resources;
204 } else {
205 streams = dice->rx_stream;
206 resources = dice->rx_resources;
207 }
208
209 for (i = 0; i < params->count; i++) {
210 if (dir == AMDTP_IN_STREAM) {
211 err = snd_dice_transaction_read_tx(dice,
212 params->size * i + TX_NUMBER_AUDIO,
213 reg, sizeof(reg));
214 } else {
215 err = snd_dice_transaction_read_rx(dice,
216 params->size * i + RX_NUMBER_AUDIO,
217 reg, sizeof(reg));
218 }
219 if (err < 0)
220 return err;
221 pcm_chs = be32_to_cpu(reg[0]);
222 midi_ports = be32_to_cpu(reg[1]);
223
224 err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
225 if (err < 0)
226 return err;
227
228 reg[0] = cpu_to_be32(resources[i].channel);
229 if (dir == AMDTP_IN_STREAM) {
230 err = snd_dice_transaction_write_tx(dice,
231 params->size * i + TX_ISOCHRONOUS,
232 reg, sizeof(reg[0]));
233 } else {
234 err = snd_dice_transaction_write_rx(dice,
235 params->size * i + RX_ISOCHRONOUS,
236 reg, sizeof(reg[0]));
237 }
238 if (err < 0)
239 return err;
240
241 if (dir == AMDTP_IN_STREAM) {
242 reg[0] = cpu_to_be32(fw_dev->max_speed);
243 err = snd_dice_transaction_write_tx(dice,
244 params->size * i + TX_SPEED,
245 reg, sizeof(reg[0]));
246 if (err < 0)
247 return err;
248 }
249
250 err = amdtp_stream_start(&streams[i], resources[i].channel,
251 fw_dev->max_speed);
252 if (err < 0)
253 return err;
254 }
255
256 return err;
257}
258
259
260
261
262
263
264int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
265{
266 unsigned int curr_rate;
267 unsigned int i;
268 struct reg_params tx_params, rx_params;
269 bool need_to_start;
270 int err;
271
272 if (dice->substreams_counter == 0)
273 return -EIO;
274
275 err = get_register_params(dice, &tx_params, &rx_params);
276 if (err < 0)
277 return err;
278
279 err = snd_dice_transaction_get_rate(dice, &curr_rate);
280 if (err < 0) {
281 dev_err(&dice->unit->device,
282 "fail to get sampling rate\n");
283 return err;
284 }
285 if (rate == 0)
286 rate = curr_rate;
287 if (rate != curr_rate)
288 return -EINVAL;
289
290
291 for (i = 0; i < MAX_STREAMS; i++) {
292 if (i < tx_params.count) {
293 if (amdtp_streaming_error(&dice->tx_stream[i]) ||
294 !amdtp_stream_running(&dice->tx_stream[i]))
295 break;
296 }
297 if (i < rx_params.count) {
298 if (amdtp_streaming_error(&dice->rx_stream[i]) ||
299 !amdtp_stream_running(&dice->rx_stream[i]))
300 break;
301 }
302 }
303 need_to_start = (i < MAX_STREAMS);
304
305 if (need_to_start) {
306
307 snd_dice_transaction_clear_enable(dice);
308 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
309 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
310 release_resources(dice);
311
312 err = ensure_phase_lock(dice);
313 if (err < 0) {
314 dev_err(&dice->unit->device,
315 "fail to ensure phase lock\n");
316 return err;
317 }
318
319
320 err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
321 if (err < 0)
322 goto error;
323 err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
324 if (err < 0)
325 goto error;
326
327 err = snd_dice_transaction_set_enable(dice);
328 if (err < 0) {
329 dev_err(&dice->unit->device,
330 "fail to enable interface\n");
331 goto error;
332 }
333
334 for (i = 0; i < MAX_STREAMS; i++) {
335 if ((i < tx_params.count &&
336 !amdtp_stream_wait_callback(&dice->tx_stream[i],
337 CALLBACK_TIMEOUT)) ||
338 (i < rx_params.count &&
339 !amdtp_stream_wait_callback(&dice->rx_stream[i],
340 CALLBACK_TIMEOUT))) {
341 err = -ETIMEDOUT;
342 goto error;
343 }
344 }
345 }
346
347 return err;
348error:
349 snd_dice_transaction_clear_enable(dice);
350 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
351 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
352 release_resources(dice);
353 return err;
354}
355
356
357
358
359
360
361void snd_dice_stream_stop_duplex(struct snd_dice *dice)
362{
363 struct reg_params tx_params, rx_params;
364
365 if (dice->substreams_counter > 0)
366 return;
367
368 snd_dice_transaction_clear_enable(dice);
369
370 if (get_register_params(dice, &tx_params, &rx_params) == 0) {
371 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
372 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
373 }
374
375 release_resources(dice);
376}
377
378static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
379 unsigned int index)
380{
381 struct amdtp_stream *stream;
382 struct fw_iso_resources *resources;
383 int err;
384
385 if (dir == AMDTP_IN_STREAM) {
386 stream = &dice->tx_stream[index];
387 resources = &dice->tx_resources[index];
388 } else {
389 stream = &dice->rx_stream[index];
390 resources = &dice->rx_resources[index];
391 }
392
393 err = fw_iso_resources_init(resources, dice->unit);
394 if (err < 0)
395 goto end;
396 resources->channels_mask = 0x00000000ffffffffuLL;
397
398 err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
399 if (err < 0) {
400 amdtp_stream_destroy(stream);
401 fw_iso_resources_destroy(resources);
402 }
403end:
404 return err;
405}
406
407
408
409
410
411static void destroy_stream(struct snd_dice *dice,
412 enum amdtp_stream_direction dir,
413 unsigned int index)
414{
415 struct amdtp_stream *stream;
416 struct fw_iso_resources *resources;
417
418 if (dir == AMDTP_IN_STREAM) {
419 stream = &dice->tx_stream[index];
420 resources = &dice->tx_resources[index];
421 } else {
422 stream = &dice->rx_stream[index];
423 resources = &dice->rx_resources[index];
424 }
425
426 amdtp_stream_destroy(stream);
427 fw_iso_resources_destroy(resources);
428}
429
430int snd_dice_stream_init_duplex(struct snd_dice *dice)
431{
432 int i, err;
433
434 for (i = 0; i < MAX_STREAMS; i++) {
435 err = init_stream(dice, AMDTP_IN_STREAM, i);
436 if (err < 0) {
437 for (; i >= 0; i--)
438 destroy_stream(dice, AMDTP_IN_STREAM, i);
439 goto end;
440 }
441 }
442
443 for (i = 0; i < MAX_STREAMS; i++) {
444 err = init_stream(dice, AMDTP_OUT_STREAM, i);
445 if (err < 0) {
446 for (; i >= 0; i--)
447 destroy_stream(dice, AMDTP_OUT_STREAM, i);
448 for (i = 0; i < MAX_STREAMS; i++)
449 destroy_stream(dice, AMDTP_IN_STREAM, i);
450 break;
451 }
452 }
453end:
454 return err;
455}
456
457void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
458{
459 unsigned int i;
460
461 for (i = 0; i < MAX_STREAMS; i++) {
462 destroy_stream(dice, AMDTP_IN_STREAM, i);
463 destroy_stream(dice, AMDTP_OUT_STREAM, i);
464 }
465}
466
467void snd_dice_stream_update_duplex(struct snd_dice *dice)
468{
469 struct reg_params tx_params, rx_params;
470
471
472
473
474
475
476
477
478
479 dice->global_enabled = false;
480
481 if (get_register_params(dice, &tx_params, &rx_params) == 0) {
482 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
483 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
484 }
485}
486
487static void dice_lock_changed(struct snd_dice *dice)
488{
489 dice->dev_lock_changed = true;
490 wake_up(&dice->hwdep_wait);
491}
492
493int snd_dice_stream_lock_try(struct snd_dice *dice)
494{
495 int err;
496
497 spin_lock_irq(&dice->lock);
498
499 if (dice->dev_lock_count < 0) {
500 err = -EBUSY;
501 goto out;
502 }
503
504 if (dice->dev_lock_count++ == 0)
505 dice_lock_changed(dice);
506 err = 0;
507out:
508 spin_unlock_irq(&dice->lock);
509 return err;
510}
511
512void snd_dice_stream_lock_release(struct snd_dice *dice)
513{
514 spin_lock_irq(&dice->lock);
515
516 if (WARN_ON(dice->dev_lock_count <= 0))
517 goto out;
518
519 if (--dice->dev_lock_count == 0)
520 dice_lock_changed(dice);
521out:
522 spin_unlock_irq(&dice->lock);
523}
524