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