0001
0002
0003
0004
0005
0006
0007
0008 #include "oxfw.h"
0009 #include <linux/delay.h>
0010
0011 #define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512
0012 #define READY_TIMEOUT_MS 600
0013
0014
0015
0016
0017
0018
0019 static const unsigned int oxfw_rate_table[] = {
0020 [0] = 32000,
0021 [1] = 44100,
0022 [2] = 48000,
0023 [3] = 88200,
0024 [4] = 96000,
0025 [5] = 192000,
0026 };
0027
0028
0029
0030
0031
0032 static const unsigned int avc_stream_rate_table[] = {
0033 [0] = 0x02,
0034 [1] = 0x03,
0035 [2] = 0x04,
0036 [3] = 0x0a,
0037 [4] = 0x05,
0038 [5] = 0x07,
0039 };
0040
0041 static int set_rate(struct snd_oxfw *oxfw, unsigned int rate)
0042 {
0043 int err;
0044
0045 err = avc_general_set_sig_fmt(oxfw->unit, rate,
0046 AVC_GENERAL_PLUG_DIR_IN, 0);
0047 if (err < 0)
0048 goto end;
0049
0050 if (oxfw->has_output)
0051 err = avc_general_set_sig_fmt(oxfw->unit, rate,
0052 AVC_GENERAL_PLUG_DIR_OUT, 0);
0053 end:
0054 return err;
0055 }
0056
0057 static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s,
0058 unsigned int rate, unsigned int pcm_channels)
0059 {
0060 u8 **formats;
0061 struct snd_oxfw_stream_formation formation;
0062 enum avc_general_plug_dir dir;
0063 unsigned int len;
0064 int i, err;
0065
0066 if (s == &oxfw->tx_stream) {
0067 formats = oxfw->tx_stream_formats;
0068 dir = AVC_GENERAL_PLUG_DIR_OUT;
0069 } else {
0070 formats = oxfw->rx_stream_formats;
0071 dir = AVC_GENERAL_PLUG_DIR_IN;
0072 }
0073
0074
0075 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0076 err = snd_oxfw_stream_parse_format(formats[i], &formation);
0077 if (err < 0)
0078 return err;
0079
0080 if ((formation.rate == rate) && (formation.pcm == pcm_channels))
0081 break;
0082 }
0083 if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
0084 return -EINVAL;
0085
0086
0087 if (oxfw->assumed)
0088 return set_rate(oxfw, rate);
0089
0090
0091 len = 5 + formats[i][4] * 2;
0092
0093 err = avc_stream_set_format(oxfw->unit, dir, 0, formats[i], len);
0094 if (err < 0)
0095 return err;
0096
0097
0098 msleep(100);
0099
0100 return 0;
0101 }
0102
0103 static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
0104 {
0105 struct cmp_connection *conn;
0106 int err;
0107
0108 if (stream == &oxfw->rx_stream)
0109 conn = &oxfw->in_conn;
0110 else
0111 conn = &oxfw->out_conn;
0112
0113 err = cmp_connection_establish(conn);
0114 if (err < 0)
0115 return err;
0116
0117 err = amdtp_domain_add_stream(&oxfw->domain, stream,
0118 conn->resources.channel, conn->speed);
0119 if (err < 0) {
0120 cmp_connection_break(conn);
0121 return err;
0122 }
0123
0124 return 0;
0125 }
0126
0127 static int check_connection_used_by_others(struct snd_oxfw *oxfw,
0128 struct amdtp_stream *stream)
0129 {
0130 struct cmp_connection *conn;
0131 bool used;
0132 int err;
0133
0134 if (stream == &oxfw->tx_stream)
0135 conn = &oxfw->out_conn;
0136 else
0137 conn = &oxfw->in_conn;
0138
0139 err = cmp_connection_check_used(conn, &used);
0140 if ((err >= 0) && used && !amdtp_stream_running(stream)) {
0141 dev_err(&oxfw->unit->device,
0142 "Connection established by others: %cPCR[%d]\n",
0143 (conn->direction == CMP_OUTPUT) ? 'o' : 'i',
0144 conn->pcr_index);
0145 err = -EBUSY;
0146 }
0147
0148 return err;
0149 }
0150
0151 static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
0152 {
0153 struct cmp_connection *conn;
0154 enum cmp_direction c_dir;
0155 enum amdtp_stream_direction s_dir;
0156 unsigned int flags = 0;
0157 int err;
0158
0159 if (!(oxfw->quirks & SND_OXFW_QUIRK_BLOCKING_TRANSMISSION))
0160 flags |= CIP_NONBLOCKING;
0161 else
0162 flags |= CIP_BLOCKING;
0163
0164
0165
0166
0167
0168 if (!(oxfw->quirks & SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET))
0169 flags |= CIP_UNAWARE_SYT;
0170
0171 if (stream == &oxfw->tx_stream) {
0172 conn = &oxfw->out_conn;
0173 c_dir = CMP_OUTPUT;
0174 s_dir = AMDTP_IN_STREAM;
0175
0176 if (oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)
0177 flags |= CIP_JUMBO_PAYLOAD;
0178 if (oxfw->quirks & SND_OXFW_QUIRK_WRONG_DBS)
0179 flags |= CIP_WRONG_DBS;
0180 } else {
0181 conn = &oxfw->in_conn;
0182 c_dir = CMP_INPUT;
0183 s_dir = AMDTP_OUT_STREAM;
0184 }
0185
0186 err = cmp_connection_init(conn, oxfw->unit, c_dir, 0);
0187 if (err < 0)
0188 return err;
0189
0190 err = amdtp_am824_init(stream, oxfw->unit, s_dir, flags);
0191 if (err < 0) {
0192 cmp_connection_destroy(conn);
0193 return err;
0194 }
0195
0196 return 0;
0197 }
0198
0199 static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
0200 {
0201 enum avc_general_plug_dir dir;
0202 u8 **formats;
0203 struct snd_oxfw_stream_formation formation;
0204 struct cmp_connection *conn;
0205 int i;
0206 int err;
0207
0208 if (stream == &oxfw->rx_stream) {
0209 dir = AVC_GENERAL_PLUG_DIR_IN;
0210 formats = oxfw->rx_stream_formats;
0211 conn = &oxfw->in_conn;
0212 } else {
0213 dir = AVC_GENERAL_PLUG_DIR_OUT;
0214 formats = oxfw->tx_stream_formats;
0215 conn = &oxfw->out_conn;
0216 }
0217
0218 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
0219 if (err < 0)
0220 return err;
0221
0222 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0223 struct snd_oxfw_stream_formation fmt;
0224
0225 if (formats[i] == NULL)
0226 break;
0227
0228 err = snd_oxfw_stream_parse_format(formats[i], &fmt);
0229 if (err < 0)
0230 return err;
0231
0232 if (fmt.rate == formation.rate && fmt.pcm == formation.pcm &&
0233 fmt.midi == formation.midi)
0234 break;
0235 }
0236 if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
0237 return -EINVAL;
0238
0239
0240 if (formation.pcm == 0)
0241 return -EINVAL;
0242
0243 err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm,
0244 formation.midi * 8, false);
0245 if (err < 0)
0246 return err;
0247
0248 return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream));
0249 }
0250
0251 int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
0252 struct amdtp_stream *stream,
0253 unsigned int rate, unsigned int pcm_channels,
0254 unsigned int frames_per_period,
0255 unsigned int frames_per_buffer)
0256 {
0257 struct snd_oxfw_stream_formation formation;
0258 enum avc_general_plug_dir dir;
0259 int err;
0260
0261
0262
0263 err = check_connection_used_by_others(oxfw, &oxfw->rx_stream);
0264 if (err < 0)
0265 return err;
0266 if (oxfw->has_output) {
0267 err = check_connection_used_by_others(oxfw, &oxfw->tx_stream);
0268 if (err < 0)
0269 return err;
0270 }
0271
0272 if (stream == &oxfw->tx_stream)
0273 dir = AVC_GENERAL_PLUG_DIR_OUT;
0274 else
0275 dir = AVC_GENERAL_PLUG_DIR_IN;
0276
0277 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
0278 if (err < 0)
0279 return err;
0280 if (rate == 0) {
0281 rate = formation.rate;
0282 pcm_channels = formation.pcm;
0283 }
0284 if (formation.rate != rate || formation.pcm != pcm_channels) {
0285 amdtp_domain_stop(&oxfw->domain);
0286
0287 cmp_connection_break(&oxfw->in_conn);
0288 cmp_connection_release(&oxfw->in_conn);
0289
0290 if (oxfw->has_output) {
0291 cmp_connection_break(&oxfw->out_conn);
0292 cmp_connection_release(&oxfw->out_conn);
0293 }
0294 }
0295
0296 if (oxfw->substreams_count == 0 ||
0297 formation.rate != rate || formation.pcm != pcm_channels) {
0298 err = set_stream_format(oxfw, stream, rate, pcm_channels);
0299 if (err < 0) {
0300 dev_err(&oxfw->unit->device,
0301 "fail to set stream format: %d\n", err);
0302 return err;
0303 }
0304
0305 err = keep_resources(oxfw, &oxfw->rx_stream);
0306 if (err < 0)
0307 return err;
0308
0309 if (oxfw->has_output) {
0310 err = keep_resources(oxfw, &oxfw->tx_stream);
0311 if (err < 0) {
0312 cmp_connection_release(&oxfw->in_conn);
0313 return err;
0314 }
0315 }
0316
0317 err = amdtp_domain_set_events_per_period(&oxfw->domain,
0318 frames_per_period, frames_per_buffer);
0319 if (err < 0) {
0320 cmp_connection_release(&oxfw->in_conn);
0321 if (oxfw->has_output)
0322 cmp_connection_release(&oxfw->out_conn);
0323 return err;
0324 }
0325 }
0326
0327 return 0;
0328 }
0329
0330 int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
0331 {
0332 int err;
0333
0334 if (oxfw->substreams_count == 0)
0335 return -EIO;
0336
0337 if (amdtp_streaming_error(&oxfw->rx_stream) ||
0338 amdtp_streaming_error(&oxfw->tx_stream)) {
0339 amdtp_domain_stop(&oxfw->domain);
0340
0341 cmp_connection_break(&oxfw->in_conn);
0342 if (oxfw->has_output)
0343 cmp_connection_break(&oxfw->out_conn);
0344 }
0345
0346 if (!amdtp_stream_running(&oxfw->rx_stream)) {
0347 unsigned int tx_init_skip_cycles = 0;
0348 bool replay_seq = false;
0349
0350 err = start_stream(oxfw, &oxfw->rx_stream);
0351 if (err < 0) {
0352 dev_err(&oxfw->unit->device,
0353 "fail to prepare rx stream: %d\n", err);
0354 goto error;
0355 }
0356
0357 if (oxfw->has_output &&
0358 !amdtp_stream_running(&oxfw->tx_stream)) {
0359 err = start_stream(oxfw, &oxfw->tx_stream);
0360 if (err < 0) {
0361 dev_err(&oxfw->unit->device,
0362 "fail to prepare tx stream: %d\n", err);
0363 goto error;
0364 }
0365
0366 if (oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD) {
0367
0368
0369 tx_init_skip_cycles = 400;
0370 } else if (oxfw->quirks & SND_OXFW_QUIRK_VOLUNTARY_RECOVERY) {
0371
0372
0373
0374 tx_init_skip_cycles = 4000;
0375 } else {
0376 replay_seq = true;
0377 }
0378 }
0379
0380
0381
0382
0383 err = amdtp_domain_start(&oxfw->domain, tx_init_skip_cycles, replay_seq, false);
0384 if (err < 0)
0385 goto error;
0386
0387 if (!amdtp_domain_wait_ready(&oxfw->domain, READY_TIMEOUT_MS)) {
0388 err = -ETIMEDOUT;
0389 goto error;
0390 }
0391 }
0392
0393 return 0;
0394 error:
0395 amdtp_domain_stop(&oxfw->domain);
0396
0397 cmp_connection_break(&oxfw->in_conn);
0398 if (oxfw->has_output)
0399 cmp_connection_break(&oxfw->out_conn);
0400
0401 return err;
0402 }
0403
0404 void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw)
0405 {
0406 if (oxfw->substreams_count == 0) {
0407 amdtp_domain_stop(&oxfw->domain);
0408
0409 cmp_connection_break(&oxfw->in_conn);
0410 cmp_connection_release(&oxfw->in_conn);
0411
0412 if (oxfw->has_output) {
0413 cmp_connection_break(&oxfw->out_conn);
0414 cmp_connection_release(&oxfw->out_conn);
0415 }
0416 }
0417 }
0418
0419 static void destroy_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
0420 {
0421 struct cmp_connection *conn;
0422
0423 if (stream == &oxfw->tx_stream)
0424 conn = &oxfw->out_conn;
0425 else
0426 conn = &oxfw->in_conn;
0427
0428 amdtp_stream_destroy(stream);
0429 cmp_connection_destroy(conn);
0430 }
0431
0432 int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw)
0433 {
0434 int err;
0435
0436 err = init_stream(oxfw, &oxfw->rx_stream);
0437 if (err < 0)
0438 return err;
0439
0440 if (oxfw->has_output) {
0441 err = init_stream(oxfw, &oxfw->tx_stream);
0442 if (err < 0) {
0443 destroy_stream(oxfw, &oxfw->rx_stream);
0444 return err;
0445 }
0446 }
0447
0448 err = amdtp_domain_init(&oxfw->domain);
0449 if (err < 0) {
0450 destroy_stream(oxfw, &oxfw->rx_stream);
0451 if (oxfw->has_output)
0452 destroy_stream(oxfw, &oxfw->tx_stream);
0453 }
0454
0455 return err;
0456 }
0457
0458
0459
0460 void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw)
0461 {
0462 amdtp_domain_destroy(&oxfw->domain);
0463
0464 destroy_stream(oxfw, &oxfw->rx_stream);
0465
0466 if (oxfw->has_output)
0467 destroy_stream(oxfw, &oxfw->tx_stream);
0468 }
0469
0470 void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw)
0471 {
0472 amdtp_domain_stop(&oxfw->domain);
0473
0474 cmp_connection_break(&oxfw->in_conn);
0475
0476 amdtp_stream_pcm_abort(&oxfw->rx_stream);
0477
0478 if (oxfw->has_output) {
0479 cmp_connection_break(&oxfw->out_conn);
0480
0481 amdtp_stream_pcm_abort(&oxfw->tx_stream);
0482 }
0483 }
0484
0485 int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
0486 enum avc_general_plug_dir dir,
0487 struct snd_oxfw_stream_formation *formation)
0488 {
0489 u8 *format;
0490 unsigned int len;
0491 int err;
0492
0493 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
0494 format = kmalloc(len, GFP_KERNEL);
0495 if (format == NULL)
0496 return -ENOMEM;
0497
0498 err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
0499 if (err < 0)
0500 goto end;
0501 if (len < 3) {
0502 err = -EIO;
0503 goto end;
0504 }
0505
0506 err = snd_oxfw_stream_parse_format(format, formation);
0507 end:
0508 kfree(format);
0509 return err;
0510 }
0511
0512
0513
0514
0515
0516
0517
0518 int snd_oxfw_stream_parse_format(u8 *format,
0519 struct snd_oxfw_stream_formation *formation)
0520 {
0521 unsigned int i, e, channels, type;
0522
0523 memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
0524
0525
0526
0527
0528
0529
0530 if ((format[0] != 0x90) || (format[1] != 0x40))
0531 return -ENXIO;
0532
0533
0534 for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
0535 if (format[2] == avc_stream_rate_table[i])
0536 break;
0537 }
0538 if (i == ARRAY_SIZE(avc_stream_rate_table))
0539 return -ENXIO;
0540
0541 formation->rate = oxfw_rate_table[i];
0542
0543 for (e = 0; e < format[4]; e++) {
0544 channels = format[5 + e * 2];
0545 type = format[6 + e * 2];
0546
0547 switch (type) {
0548
0549 case 0x00:
0550
0551 case 0x06:
0552 formation->pcm += channels;
0553 break;
0554
0555 case 0x0d:
0556 formation->midi = channels;
0557 break;
0558
0559 case 0x01:
0560 case 0x02:
0561 case 0x03:
0562 case 0x04:
0563 case 0x05:
0564
0565 case 0x07:
0566 case 0x0c:
0567
0568 case 0x08:
0569 case 0x09:
0570 case 0x0a:
0571 case 0x0b:
0572
0573 case 0x0e:
0574
0575 case 0x0f:
0576
0577 case 0x10:
0578
0579 case 0x40:
0580
0581 case 0xff:
0582 default:
0583 return -ENXIO;
0584 }
0585 }
0586
0587 if (formation->pcm > AM824_MAX_CHANNELS_FOR_PCM ||
0588 formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
0589 return -ENXIO;
0590
0591 return 0;
0592 }
0593
0594 static int
0595 assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
0596 unsigned int pid, u8 *buf, unsigned int *len,
0597 u8 **formats)
0598 {
0599 struct snd_oxfw_stream_formation formation;
0600 unsigned int i, eid;
0601 int err;
0602
0603
0604 err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
0605 if (err < 0) {
0606 dev_err(&oxfw->unit->device,
0607 "fail to get current stream format for isoc %s plug %d:%d\n",
0608 (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
0609 pid, err);
0610 goto end;
0611 }
0612
0613
0614 eid = 0;
0615 err = snd_oxfw_stream_parse_format(buf, &formation);
0616 if (err < 0)
0617 goto end;
0618
0619 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
0620 GFP_KERNEL);
0621 if (!formats[eid]) {
0622 err = -ENOMEM;
0623 goto end;
0624 }
0625
0626
0627 for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
0628 if (formation.rate == oxfw_rate_table[i])
0629 continue;
0630
0631 err = avc_general_inquiry_sig_fmt(oxfw->unit,
0632 oxfw_rate_table[i],
0633 dir, pid);
0634 if (err < 0)
0635 continue;
0636
0637 eid++;
0638 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
0639 GFP_KERNEL);
0640 if (formats[eid] == NULL) {
0641 err = -ENOMEM;
0642 goto end;
0643 }
0644 formats[eid][2] = avc_stream_rate_table[i];
0645 }
0646
0647 err = 0;
0648 oxfw->assumed = true;
0649 end:
0650 return err;
0651 }
0652
0653 static int fill_stream_formats(struct snd_oxfw *oxfw,
0654 enum avc_general_plug_dir dir,
0655 unsigned short pid)
0656 {
0657 u8 *buf, **formats;
0658 unsigned int len, eid = 0;
0659 struct snd_oxfw_stream_formation dummy;
0660 int err;
0661
0662 buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
0663 if (buf == NULL)
0664 return -ENOMEM;
0665
0666 if (dir == AVC_GENERAL_PLUG_DIR_OUT)
0667 formats = oxfw->tx_stream_formats;
0668 else
0669 formats = oxfw->rx_stream_formats;
0670
0671
0672 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
0673 err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
0674 if (err == -ENXIO) {
0675
0676 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
0677 err = assume_stream_formats(oxfw, dir, pid, buf, &len,
0678 formats);
0679 goto end;
0680 } else if (err < 0) {
0681 dev_err(&oxfw->unit->device,
0682 "fail to get stream format %d for isoc %s plug %d:%d\n",
0683 eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
0684 pid, err);
0685 goto end;
0686 }
0687
0688
0689 while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
0690
0691 if (len < 3) {
0692 err = -EIO;
0693 break;
0694 }
0695
0696
0697 err = snd_oxfw_stream_parse_format(buf, &dummy);
0698 if (err < 0)
0699 break;
0700
0701 formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, len,
0702 GFP_KERNEL);
0703 if (!formats[eid]) {
0704 err = -ENOMEM;
0705 break;
0706 }
0707
0708
0709 len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
0710 err = avc_stream_get_format_list(oxfw->unit, dir, 0,
0711 buf, &len, ++eid);
0712
0713 if (err == -EINVAL) {
0714 err = 0;
0715 break;
0716 } else if (err < 0) {
0717 dev_err(&oxfw->unit->device,
0718 "fail to get stream format %d for isoc %s plug %d:%d\n",
0719 eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
0720 "out",
0721 pid, err);
0722 break;
0723 }
0724 }
0725 end:
0726 kfree(buf);
0727 return err;
0728 }
0729
0730 int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
0731 {
0732 u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
0733 struct snd_oxfw_stream_formation formation;
0734 u8 *format;
0735 unsigned int i;
0736 int err;
0737
0738
0739 err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
0740 if (err < 0) {
0741 dev_err(&oxfw->unit->device,
0742 "fail to get info for isoc/external in/out plugs: %d\n",
0743 err);
0744 goto end;
0745 } else if ((plugs[0] == 0) && (plugs[1] == 0)) {
0746 err = -ENXIO;
0747 goto end;
0748 }
0749
0750
0751 if (plugs[1] > 0) {
0752 err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
0753 if (err < 0) {
0754 if (err != -ENXIO)
0755 return err;
0756
0757
0758 err = 0;
0759 } else {
0760 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0761 format = oxfw->tx_stream_formats[i];
0762 if (format == NULL)
0763 continue;
0764 err = snd_oxfw_stream_parse_format(format,
0765 &formation);
0766 if (err < 0)
0767 continue;
0768
0769
0770 if (formation.midi > 0)
0771 oxfw->midi_input_ports = 1;
0772 }
0773
0774 oxfw->has_output = true;
0775 }
0776 }
0777
0778
0779 if (plugs[0] > 0) {
0780 err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
0781 if (err < 0) {
0782 if (err != -ENXIO)
0783 return err;
0784
0785
0786 err = 0;
0787 } else {
0788 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0789 format = oxfw->rx_stream_formats[i];
0790 if (format == NULL)
0791 continue;
0792 err = snd_oxfw_stream_parse_format(format,
0793 &formation);
0794 if (err < 0)
0795 continue;
0796
0797
0798 if (formation.midi > 0)
0799 oxfw->midi_output_ports = 1;
0800 }
0801
0802 oxfw->has_input = true;
0803 }
0804 }
0805 end:
0806 return err;
0807 }
0808
0809 void snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw)
0810 {
0811 oxfw->dev_lock_changed = true;
0812 wake_up(&oxfw->hwdep_wait);
0813 }
0814
0815 int snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw)
0816 {
0817 int err;
0818
0819 spin_lock_irq(&oxfw->lock);
0820
0821
0822 if (oxfw->dev_lock_count < 0) {
0823 err = -EBUSY;
0824 goto end;
0825 }
0826
0827
0828 if (oxfw->dev_lock_count++ == 0)
0829 snd_oxfw_stream_lock_changed(oxfw);
0830 err = 0;
0831 end:
0832 spin_unlock_irq(&oxfw->lock);
0833 return err;
0834 }
0835
0836 void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw)
0837 {
0838 spin_lock_irq(&oxfw->lock);
0839
0840 if (WARN_ON(oxfw->dev_lock_count <= 0))
0841 goto end;
0842 if (--oxfw->dev_lock_count == 0)
0843 snd_oxfw_stream_lock_changed(oxfw);
0844 end:
0845 spin_unlock_irq(&oxfw->lock);
0846 }