ALSA: firewire-lib: use variable size of queue for isoc packets instead of fixed...
[linux-2.6-block.git] / sound / firewire / oxfw / oxfw-stream.c
CommitLineData
da607e19 1// SPDX-License-Identifier: GPL-2.0-only
e2786ca6
TS
2/*
3 * oxfw_stream.c - a part of driver for OXFW970/971 based devices
4 *
5 * Copyright (c) 2014 Takashi Sakamoto
e2786ca6
TS
6 */
7
8#include "oxfw.h"
f3699e2c 9#include <linux/delay.h>
e2786ca6 10
5cd1d3f4 11#define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512
f3699e2c 12#define CALLBACK_TIMEOUT 200
5cd1d3f4
TS
13
14/*
15 * According to datasheet of Oxford Semiconductor:
16 * OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O
17 * OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O
18 */
19static const unsigned int oxfw_rate_table[] = {
20 [0] = 32000,
21 [1] = 44100,
22 [2] = 48000,
23 [3] = 88200,
24 [4] = 96000,
25 [5] = 192000,
26};
27
28/*
29 * See Table 5.7 – Sampling frequency for Multi-bit Audio
30 * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
31 */
32static const unsigned int avc_stream_rate_table[] = {
33 [0] = 0x02,
34 [1] = 0x03,
35 [2] = 0x04,
36 [3] = 0x0a,
37 [4] = 0x05,
38 [5] = 0x07,
39};
40
b0ac0009
TS
41static int set_rate(struct snd_oxfw *oxfw, unsigned int rate)
42{
43 int err;
44
45 err = avc_general_set_sig_fmt(oxfw->unit, rate,
46 AVC_GENERAL_PLUG_DIR_IN, 0);
47 if (err < 0)
48 goto end;
49
50 if (oxfw->has_output)
51 err = avc_general_set_sig_fmt(oxfw->unit, rate,
52 AVC_GENERAL_PLUG_DIR_OUT, 0);
53end:
54 return err;
55}
56
f3699e2c
TS
57static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s,
58 unsigned int rate, unsigned int pcm_channels)
59{
60 u8 **formats;
61 struct snd_oxfw_stream_formation formation;
62 enum avc_general_plug_dir dir;
5580ba7b
DC
63 unsigned int len;
64 int i, err;
f3699e2c 65
b0ac0009
TS
66 if (s == &oxfw->tx_stream) {
67 formats = oxfw->tx_stream_formats;
68 dir = AVC_GENERAL_PLUG_DIR_OUT;
69 } else {
70 formats = oxfw->rx_stream_formats;
71 dir = AVC_GENERAL_PLUG_DIR_IN;
72 }
f3699e2c
TS
73
74 /* Seek stream format for requirements. */
75 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
76 err = snd_oxfw_stream_parse_format(formats[i], &formation);
77 if (err < 0)
78 return err;
79
80 if ((formation.rate == rate) && (formation.pcm == pcm_channels))
81 break;
82 }
83 if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
84 return -EINVAL;
85
86 /* If assumed, just change rate. */
87 if (oxfw->assumed)
b0ac0009 88 return set_rate(oxfw, rate);
f3699e2c
TS
89
90 /* Calculate format length. */
91 len = 5 + formats[i][4] * 2;
92
93 err = avc_stream_set_format(oxfw->unit, dir, 0, formats[i], len);
94 if (err < 0)
95 return err;
96
97 /* Some requests just after changing format causes freezing. */
98 msleep(100);
99
100 return 0;
101}
102
521b2e11 103static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
e2786ca6 104{
f3699e2c 105 struct cmp_connection *conn;
f3699e2c 106 int err;
e2786ca6 107
0356ce3a 108 if (stream == &oxfw->rx_stream)
b0ac0009 109 conn = &oxfw->in_conn;
0356ce3a 110 else
b0ac0009 111 conn = &oxfw->out_conn;
e2786ca6 112
7bc93821 113 err = cmp_connection_establish(conn);
e2786ca6 114 if (err < 0)
e34244dd 115 return err;
e2786ca6 116
ac5d7786
TS
117 err = amdtp_domain_add_stream(&oxfw->domain, stream,
118 conn->resources.channel, conn->speed);
f3699e2c
TS
119 if (err < 0) {
120 cmp_connection_break(conn);
e34244dd 121 return err;
f3699e2c
TS
122 }
123
e34244dd 124 return 0;
f3699e2c
TS
125}
126
b0ac0009
TS
127static int check_connection_used_by_others(struct snd_oxfw *oxfw,
128 struct amdtp_stream *stream)
f3699e2c 129{
b0ac0009
TS
130 struct cmp_connection *conn;
131 bool used;
132 int err;
133
134 if (stream == &oxfw->tx_stream)
135 conn = &oxfw->out_conn;
136 else
137 conn = &oxfw->in_conn;
138
139 err = cmp_connection_check_used(conn, &used);
140 if ((err >= 0) && used && !amdtp_stream_running(stream)) {
141 dev_err(&oxfw->unit->device,
142 "Connection established by others: %cPCR[%d]\n",
143 (conn->direction == CMP_OUTPUT) ? 'o' : 'i',
144 conn->pcr_index);
145 err = -EBUSY;
146 }
147
148 return err;
149}
150
779f0dba 151static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
b0ac0009
TS
152{
153 struct cmp_connection *conn;
154 enum cmp_direction c_dir;
155 enum amdtp_stream_direction s_dir;
156 int err;
157
158 if (stream == &oxfw->tx_stream) {
159 conn = &oxfw->out_conn;
160 c_dir = CMP_OUTPUT;
161 s_dir = AMDTP_IN_STREAM;
162 } else {
163 conn = &oxfw->in_conn;
164 c_dir = CMP_INPUT;
165 s_dir = AMDTP_OUT_STREAM;
166 }
167
168 err = cmp_connection_init(conn, oxfw->unit, c_dir, 0);
169 if (err < 0)
779f0dba 170 return err;
b0ac0009 171
5955815e 172 err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
b0ac0009 173 if (err < 0) {
b0ac0009 174 cmp_connection_destroy(conn);
779f0dba 175 return err;
b0ac0009
TS
176 }
177
a2064710
TS
178 /*
179 * OXFW starts to transmit packets with non-zero dbc.
180 * OXFW postpone transferring packets till handling any asynchronous
181 * packets. As a result, next isochronous packet includes more data
182 * blocks than IEC 61883-6 defines.
183 */
13f3a46d 184 if (stream == &oxfw->tx_stream) {
62f00e40 185 oxfw->tx_stream.flags |= CIP_JUMBO_PAYLOAD;
13f3a46d
TS
186 if (oxfw->wrong_dbs)
187 oxfw->tx_stream.flags |= CIP_WRONG_DBS;
188 }
779f0dba
TS
189
190 return 0;
b0ac0009
TS
191}
192
0356ce3a
TS
193static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
194{
195 enum avc_general_plug_dir dir;
196 u8 **formats;
197 struct snd_oxfw_stream_formation formation;
7bc93821 198 struct cmp_connection *conn;
0356ce3a
TS
199 int i;
200 int err;
201
202 if (stream == &oxfw->rx_stream) {
203 dir = AVC_GENERAL_PLUG_DIR_IN;
204 formats = oxfw->rx_stream_formats;
7bc93821 205 conn = &oxfw->in_conn;
0356ce3a
TS
206 } else {
207 dir = AVC_GENERAL_PLUG_DIR_OUT;
208 formats = oxfw->tx_stream_formats;
7bc93821 209 conn = &oxfw->out_conn;
0356ce3a
TS
210 }
211
212 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
213 if (err < 0)
214 return err;
215
216 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
217 struct snd_oxfw_stream_formation fmt;
218
219 if (formats[i] == NULL)
220 break;
221
222 err = snd_oxfw_stream_parse_format(formats[i], &fmt);
223 if (err < 0)
224 return err;
225
226 if (fmt.rate == formation.rate && fmt.pcm == formation.pcm &&
227 fmt.midi == formation.midi)
228 break;
229 }
230 if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
231 return -EINVAL;
232
233 // The stream should have one pcm channels at least.
234 if (formation.pcm == 0)
235 return -EINVAL;
236
7bc93821 237 err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm,
0356ce3a 238 formation.midi * 8, false);
7bc93821
TS
239 if (err < 0)
240 return err;
241
242 return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream));
0356ce3a
TS
243}
244
4f380d00
TS
245int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
246 struct amdtp_stream *stream,
1d6a722c
TS
247 unsigned int rate, unsigned int pcm_channels,
248 unsigned int frames_per_period)
b0ac0009 249{
f3699e2c 250 struct snd_oxfw_stream_formation formation;
b0ac0009 251 enum avc_general_plug_dir dir;
4f380d00 252 int err;
b0ac0009 253
20358d44
TS
254 // Considering JACK/FFADO streaming:
255 // TODO: This can be removed hwdep functionality becomes popular.
256 err = check_connection_used_by_others(oxfw, &oxfw->rx_stream);
257 if (err < 0)
258 return err;
259 if (oxfw->has_output) {
260 err = check_connection_used_by_others(oxfw, &oxfw->tx_stream);
261 if (err < 0)
262 return err;
b0ac0009
TS
263 }
264
20358d44
TS
265 if (stream == &oxfw->tx_stream)
266 dir = AVC_GENERAL_PLUG_DIR_OUT;
267 else
268 dir = AVC_GENERAL_PLUG_DIR_IN;
b0ac0009 269
b0ac0009 270 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
e2786ca6 271 if (err < 0)
20358d44 272 return err;
4f380d00 273 if (rate == 0) {
05588d34 274 rate = formation.rate;
05588d34 275 pcm_channels = formation.pcm;
4f380d00
TS
276 }
277 if (formation.rate != rate || formation.pcm != pcm_channels) {
ac5d7786
TS
278 amdtp_domain_stop(&oxfw->domain);
279
e34244dd 280 cmp_connection_break(&oxfw->in_conn);
3f2ce83d 281 cmp_connection_release(&oxfw->in_conn);
e34244dd
TS
282
283 if (oxfw->has_output) {
e34244dd 284 cmp_connection_break(&oxfw->out_conn);
3f2ce83d 285 cmp_connection_release(&oxfw->out_conn);
e34244dd 286 }
4f380d00 287 }
f3699e2c 288
4f380d00
TS
289 if (oxfw->substreams_count == 0 ||
290 formation.rate != rate || formation.pcm != pcm_channels) {
b0ac0009 291 err = set_stream_format(oxfw, stream, rate, pcm_channels);
f3699e2c
TS
292 if (err < 0) {
293 dev_err(&oxfw->unit->device,
294 "fail to set stream format: %d\n", err);
20358d44 295 return err;
f3699e2c 296 }
0356ce3a
TS
297
298 err = keep_resources(oxfw, &oxfw->rx_stream);
299 if (err < 0)
300 return err;
301
302 if (oxfw->has_output) {
303 err = keep_resources(oxfw, &oxfw->tx_stream);
7bc93821
TS
304 if (err < 0) {
305 cmp_connection_release(&oxfw->in_conn);
0356ce3a 306 return err;
7bc93821 307 }
0356ce3a 308 }
1d6a722c
TS
309
310 err = amdtp_domain_set_events_per_period(&oxfw->domain,
a0e02331 311 frames_per_period, 0);
1d6a722c
TS
312 if (err < 0) {
313 cmp_connection_release(&oxfw->in_conn);
314 if (oxfw->has_output)
315 cmp_connection_release(&oxfw->out_conn);
316 return err;
317 }
20358d44 318 }
b0ac0009 319
4f380d00
TS
320 return 0;
321}
322
323int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
324{
325 int err;
326
327 if (oxfw->substreams_count == 0)
328 return -EIO;
329
330 if (amdtp_streaming_error(&oxfw->rx_stream) ||
331 amdtp_streaming_error(&oxfw->tx_stream)) {
ac5d7786 332 amdtp_domain_stop(&oxfw->domain);
4f380d00 333
ac5d7786
TS
334 cmp_connection_break(&oxfw->in_conn);
335 if (oxfw->has_output)
4f380d00 336 cmp_connection_break(&oxfw->out_conn);
4f380d00
TS
337 }
338
20358d44
TS
339 if (!amdtp_stream_running(&oxfw->rx_stream)) {
340 err = start_stream(oxfw, &oxfw->rx_stream);
341 if (err < 0) {
342 dev_err(&oxfw->unit->device,
ac5d7786 343 "fail to prepare rx stream: %d\n", err);
20358d44
TS
344 goto error;
345 }
20358d44 346
ac5d7786
TS
347 if (oxfw->has_output &&
348 !amdtp_stream_running(&oxfw->tx_stream)) {
20358d44 349 err = start_stream(oxfw, &oxfw->tx_stream);
b0ac0009
TS
350 if (err < 0) {
351 dev_err(&oxfw->unit->device,
ac5d7786 352 "fail to prepare tx stream: %d\n", err);
20358d44 353 goto error;
b0ac0009
TS
354 }
355 }
ac5d7786
TS
356
357 err = amdtp_domain_start(&oxfw->domain);
358 if (err < 0)
359 goto error;
360
361 // Wait first packet.
362 if (!amdtp_stream_wait_callback(&oxfw->rx_stream,
ac5d7786
TS
363 CALLBACK_TIMEOUT)) {
364 err = -ETIMEDOUT;
365 goto error;
366 }
367
4c098dab
TS
368 if (oxfw->has_output) {
369 if (!amdtp_stream_wait_callback(&oxfw->tx_stream,
370 CALLBACK_TIMEOUT)) {
371 err = -ETIMEDOUT;
372 goto error;
373 }
374 }
f3699e2c
TS
375 }
376
20358d44
TS
377 return 0;
378error:
ac5d7786
TS
379 amdtp_domain_stop(&oxfw->domain);
380
20358d44 381 cmp_connection_break(&oxfw->in_conn);
ac5d7786 382 if (oxfw->has_output)
20358d44 383 cmp_connection_break(&oxfw->out_conn);
ac5d7786 384
e2786ca6
TS
385 return err;
386}
387
779f0dba 388void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw)
e2786ca6 389{
4a0a0472 390 if (oxfw->substreams_count == 0) {
ac5d7786
TS
391 amdtp_domain_stop(&oxfw->domain);
392
e34244dd 393 cmp_connection_break(&oxfw->in_conn);
7bc93821 394 cmp_connection_release(&oxfw->in_conn);
b0ac0009 395
e34244dd 396 if (oxfw->has_output) {
e34244dd 397 cmp_connection_break(&oxfw->out_conn);
7bc93821 398 cmp_connection_release(&oxfw->out_conn);
e34244dd 399 }
20358d44 400 }
e2786ca6
TS
401}
402
779f0dba 403static void destroy_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
e2786ca6 404{
b0ac0009
TS
405 struct cmp_connection *conn;
406
407 if (stream == &oxfw->tx_stream)
408 conn = &oxfw->out_conn;
409 else
410 conn = &oxfw->in_conn;
e2786ca6 411
b0ac0009
TS
412 amdtp_stream_destroy(stream);
413 cmp_connection_destroy(conn);
e2786ca6
TS
414}
415
779f0dba
TS
416int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw)
417{
418 int err;
419
420 err = init_stream(oxfw, &oxfw->rx_stream);
421 if (err < 0)
422 return err;
423
424 if (oxfw->has_output) {
425 err = init_stream(oxfw, &oxfw->tx_stream);
426 if (err < 0) {
427 destroy_stream(oxfw, &oxfw->rx_stream);
428 return err;
429 }
430 }
431
ac5d7786
TS
432 err = amdtp_domain_init(&oxfw->domain);
433 if (err < 0) {
434 destroy_stream(oxfw, &oxfw->rx_stream);
435 if (oxfw->has_output)
436 destroy_stream(oxfw, &oxfw->tx_stream);
437 }
438
439 return err;
779f0dba
TS
440}
441
442// This function should be called before starting the stream or after stopping
443// the streams.
444void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw)
445{
ac5d7786
TS
446 amdtp_domain_destroy(&oxfw->domain);
447
779f0dba
TS
448 destroy_stream(oxfw, &oxfw->rx_stream);
449
450 if (oxfw->has_output)
451 destroy_stream(oxfw, &oxfw->tx_stream);
452}
453
454void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw)
e2786ca6 455{
ac5d7786
TS
456 amdtp_domain_stop(&oxfw->domain);
457
e34244dd 458 cmp_connection_break(&oxfw->in_conn);
b0ac0009 459
e34244dd
TS
460 amdtp_stream_pcm_abort(&oxfw->rx_stream);
461
462 if (oxfw->has_output) {
e34244dd
TS
463 cmp_connection_break(&oxfw->out_conn);
464
465 amdtp_stream_pcm_abort(&oxfw->tx_stream);
466 }
e2786ca6 467}
5cd1d3f4 468
3c96101f
TS
469int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
470 enum avc_general_plug_dir dir,
471 struct snd_oxfw_stream_formation *formation)
472{
473 u8 *format;
474 unsigned int len;
475 int err;
476
477 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
478 format = kmalloc(len, GFP_KERNEL);
479 if (format == NULL)
480 return -ENOMEM;
481
482 err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
483 if (err < 0)
484 goto end;
485 if (len < 3) {
486 err = -EIO;
487 goto end;
488 }
489
490 err = snd_oxfw_stream_parse_format(format, formation);
491end:
492 kfree(format);
493 return err;
494}
495
5cd1d3f4
TS
496/*
497 * See Table 6.16 - AM824 Stream Format
498 * Figure 6.19 - format_information field for AM824 Compound
499 * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
500 * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
501 */
502int snd_oxfw_stream_parse_format(u8 *format,
503 struct snd_oxfw_stream_formation *formation)
504{
505 unsigned int i, e, channels, type;
506
507 memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
508
509 /*
510 * this module can support a hierarchy combination that:
511 * Root: Audio and Music (0x90)
512 * Level 1: AM824 Compound (0x40)
513 */
514 if ((format[0] != 0x90) || (format[1] != 0x40))
515 return -ENOSYS;
516
517 /* check the sampling rate */
518 for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
519 if (format[2] == avc_stream_rate_table[i])
520 break;
521 }
522 if (i == ARRAY_SIZE(avc_stream_rate_table))
523 return -ENOSYS;
524
525 formation->rate = oxfw_rate_table[i];
526
527 for (e = 0; e < format[4]; e++) {
528 channels = format[5 + e * 2];
529 type = format[6 + e * 2];
530
531 switch (type) {
532 /* IEC 60958 Conformant, currently handled as MBLA */
533 case 0x00:
534 /* Multi Bit Linear Audio (Raw) */
535 case 0x06:
536 formation->pcm += channels;
537 break;
538 /* MIDI Conformant */
539 case 0x0d:
540 formation->midi = channels;
541 break;
542 /* IEC 61937-3 to 7 */
543 case 0x01:
544 case 0x02:
545 case 0x03:
546 case 0x04:
547 case 0x05:
548 /* Multi Bit Linear Audio */
549 case 0x07: /* DVD-Audio */
550 case 0x0c: /* High Precision */
551 /* One Bit Audio */
552 case 0x08: /* (Plain) Raw */
553 case 0x09: /* (Plain) SACD */
554 case 0x0a: /* (Encoded) Raw */
555 case 0x0b: /* (Encoded) SACD */
556 /* SMPTE Time-Code conformant */
557 case 0x0e:
558 /* Sample Count */
559 case 0x0f:
560 /* Anciliary Data */
561 case 0x10:
562 /* Synchronization Stream (Stereo Raw audio) */
563 case 0x40:
564 /* Don't care */
565 case 0xff:
566 default:
567 return -ENOSYS; /* not supported */
568 }
569 }
570
49c7b3fc
TS
571 if (formation->pcm > AM824_MAX_CHANNELS_FOR_PCM ||
572 formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
5cd1d3f4
TS
573 return -ENOSYS;
574
575 return 0;
576}
577
578static int
579assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
580 unsigned int pid, u8 *buf, unsigned int *len,
581 u8 **formats)
582{
583 struct snd_oxfw_stream_formation formation;
584 unsigned int i, eid;
585 int err;
586
587 /* get format at current sampling rate */
588 err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
589 if (err < 0) {
590 dev_err(&oxfw->unit->device,
591 "fail to get current stream format for isoc %s plug %d:%d\n",
592 (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
593 pid, err);
594 goto end;
595 }
596
597 /* parse and set stream format */
598 eid = 0;
599 err = snd_oxfw_stream_parse_format(buf, &formation);
600 if (err < 0)
601 goto end;
602
cd3b7116
TS
603 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
604 GFP_KERNEL);
605 if (!formats[eid]) {
5cd1d3f4
TS
606 err = -ENOMEM;
607 goto end;
608 }
5cd1d3f4
TS
609
610 /* apply the format for each available sampling rate */
611 for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
612 if (formation.rate == oxfw_rate_table[i])
613 continue;
614
615 err = avc_general_inquiry_sig_fmt(oxfw->unit,
616 oxfw_rate_table[i],
617 dir, pid);
618 if (err < 0)
619 continue;
620
621 eid++;
cd3b7116
TS
622 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
623 GFP_KERNEL);
5cd1d3f4
TS
624 if (formats[eid] == NULL) {
625 err = -ENOMEM;
626 goto end;
627 }
5cd1d3f4
TS
628 formats[eid][2] = avc_stream_rate_table[i];
629 }
630
631 err = 0;
632 oxfw->assumed = true;
633end:
634 return err;
635}
636
637static int fill_stream_formats(struct snd_oxfw *oxfw,
638 enum avc_general_plug_dir dir,
639 unsigned short pid)
640{
641 u8 *buf, **formats;
642 unsigned int len, eid = 0;
643 struct snd_oxfw_stream_formation dummy;
644 int err;
645
646 buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
647 if (buf == NULL)
648 return -ENOMEM;
649
b0ac0009
TS
650 if (dir == AVC_GENERAL_PLUG_DIR_OUT)
651 formats = oxfw->tx_stream_formats;
652 else
653 formats = oxfw->rx_stream_formats;
5cd1d3f4
TS
654
655 /* get first entry */
656 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
657 err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
658 if (err == -ENOSYS) {
659 /* LIST subfunction is not implemented */
660 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
661 err = assume_stream_formats(oxfw, dir, pid, buf, &len,
662 formats);
663 goto end;
664 } else if (err < 0) {
665 dev_err(&oxfw->unit->device,
666 "fail to get stream format %d for isoc %s plug %d:%d\n",
667 eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
668 pid, err);
669 goto end;
670 }
671
672 /* LIST subfunction is implemented */
673 while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
674 /* The format is too short. */
675 if (len < 3) {
676 err = -EIO;
677 break;
678 }
679
680 /* parse and set stream format */
681 err = snd_oxfw_stream_parse_format(buf, &dummy);
682 if (err < 0)
683 break;
684
cd3b7116
TS
685 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, len,
686 GFP_KERNEL);
687 if (!formats[eid]) {
5cd1d3f4
TS
688 err = -ENOMEM;
689 break;
690 }
5cd1d3f4
TS
691
692 /* get next entry */
693 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
694 err = avc_stream_get_format_list(oxfw->unit, dir, 0,
695 buf, &len, ++eid);
696 /* No entries remained. */
697 if (err == -EINVAL) {
698 err = 0;
699 break;
700 } else if (err < 0) {
701 dev_err(&oxfw->unit->device,
702 "fail to get stream format %d for isoc %s plug %d:%d\n",
703 eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
704 "out",
705 pid, err);
706 break;
707 }
708 }
709end:
710 kfree(buf);
711 return err;
712}
713
714int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
715{
716 u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
32056041
TS
717 struct snd_oxfw_stream_formation formation;
718 u8 *format;
719 unsigned int i;
5cd1d3f4
TS
720 int err;
721
722 /* the number of plugs for isoc in/out, ext in/out */
723 err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
724 if (err < 0) {
725 dev_err(&oxfw->unit->device,
726 "fail to get info for isoc/external in/out plugs: %d\n",
727 err);
728 goto end;
b0ac0009 729 } else if ((plugs[0] == 0) && (plugs[1] == 0)) {
5cd1d3f4
TS
730 err = -ENOSYS;
731 goto end;
732 }
733
b0ac0009
TS
734 /* use oPCR[0] if exists */
735 if (plugs[1] > 0) {
736 err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
737 if (err < 0)
738 goto end;
32056041
TS
739
740 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
741 format = oxfw->tx_stream_formats[i];
742 if (format == NULL)
743 continue;
744 err = snd_oxfw_stream_parse_format(format, &formation);
745 if (err < 0)
746 continue;
747
748 /* Add one MIDI port. */
749 if (formation.midi > 0)
750 oxfw->midi_input_ports = 1;
751 }
752
b0ac0009
TS
753 oxfw->has_output = true;
754 }
755
5cd1d3f4 756 /* use iPCR[0] if exists */
32056041 757 if (plugs[0] > 0) {
5cd1d3f4 758 err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
32056041
TS
759 if (err < 0)
760 goto end;
761
762 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
763 format = oxfw->rx_stream_formats[i];
764 if (format == NULL)
765 continue;
766 err = snd_oxfw_stream_parse_format(format, &formation);
767 if (err < 0)
768 continue;
769
770 /* Add one MIDI port. */
771 if (formation.midi > 0)
772 oxfw->midi_output_ports = 1;
773 }
774 }
5cd1d3f4
TS
775end:
776 return err;
777}
8985f4ac
TS
778
779void snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw)
780{
781 oxfw->dev_lock_changed = true;
782 wake_up(&oxfw->hwdep_wait);
783}
784
785int snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw)
786{
787 int err;
788
789 spin_lock_irq(&oxfw->lock);
790
791 /* user land lock this */
792 if (oxfw->dev_lock_count < 0) {
793 err = -EBUSY;
794 goto end;
795 }
796
797 /* this is the first time */
798 if (oxfw->dev_lock_count++ == 0)
799 snd_oxfw_stream_lock_changed(oxfw);
800 err = 0;
801end:
802 spin_unlock_irq(&oxfw->lock);
803 return err;
804}
805
806void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw)
807{
808 spin_lock_irq(&oxfw->lock);
809
810 if (WARN_ON(oxfw->dev_lock_count <= 0))
811 goto end;
812 if (--oxfw->dev_lock_count == 0)
813 snd_oxfw_stream_lock_changed(oxfw);
814end:
815 spin_unlock_irq(&oxfw->lock);
816}