0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "dice.h"
0010
0011 #define READY_TIMEOUT_MS 200
0012 #define NOTIFICATION_TIMEOUT_MS 100
0013
0014 struct reg_params {
0015 unsigned int count;
0016 unsigned int size;
0017 };
0018
0019 const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
0020
0021 [0] = 32000,
0022 [1] = 44100,
0023 [2] = 48000,
0024
0025 [3] = 88200,
0026 [4] = 96000,
0027
0028 [5] = 176400,
0029 [6] = 192000,
0030 };
0031
0032 int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
0033 enum snd_dice_rate_mode *mode)
0034 {
0035
0036 static const enum snd_dice_rate_mode modes[] = {
0037 [0] = SND_DICE_RATE_MODE_LOW,
0038 [1] = SND_DICE_RATE_MODE_LOW,
0039 [2] = SND_DICE_RATE_MODE_LOW,
0040 [3] = SND_DICE_RATE_MODE_MIDDLE,
0041 [4] = SND_DICE_RATE_MODE_MIDDLE,
0042 [5] = SND_DICE_RATE_MODE_HIGH,
0043 [6] = SND_DICE_RATE_MODE_HIGH,
0044 };
0045 int i;
0046
0047 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
0048 if (!(dice->clock_caps & BIT(i)))
0049 continue;
0050 if (snd_dice_rates[i] != rate)
0051 continue;
0052
0053 *mode = modes[i];
0054 return 0;
0055 }
0056
0057 return -EINVAL;
0058 }
0059
0060 static int select_clock(struct snd_dice *dice, unsigned int rate)
0061 {
0062 __be32 reg;
0063 u32 data;
0064 int i;
0065 int err;
0066
0067 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
0068 ®, sizeof(reg));
0069 if (err < 0)
0070 return err;
0071
0072 data = be32_to_cpu(reg);
0073
0074 data &= ~CLOCK_RATE_MASK;
0075 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
0076 if (snd_dice_rates[i] == rate)
0077 break;
0078 }
0079 if (i == ARRAY_SIZE(snd_dice_rates))
0080 return -EINVAL;
0081 data |= i << CLOCK_RATE_SHIFT;
0082
0083 if (completion_done(&dice->clock_accepted))
0084 reinit_completion(&dice->clock_accepted);
0085
0086 reg = cpu_to_be32(data);
0087 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
0088 ®, sizeof(reg));
0089 if (err < 0)
0090 return err;
0091
0092 if (wait_for_completion_timeout(&dice->clock_accepted,
0093 msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0)
0094 return -ETIMEDOUT;
0095
0096 return 0;
0097 }
0098
0099 static int get_register_params(struct snd_dice *dice,
0100 struct reg_params *tx_params,
0101 struct reg_params *rx_params)
0102 {
0103 __be32 reg[2];
0104 int err;
0105
0106 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
0107 if (err < 0)
0108 return err;
0109 tx_params->count =
0110 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
0111 tx_params->size = be32_to_cpu(reg[1]) * 4;
0112
0113 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
0114 if (err < 0)
0115 return err;
0116 rx_params->count =
0117 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
0118 rx_params->size = be32_to_cpu(reg[1]) * 4;
0119
0120 return 0;
0121 }
0122
0123 static void release_resources(struct snd_dice *dice)
0124 {
0125 int i;
0126
0127 for (i = 0; i < MAX_STREAMS; ++i) {
0128 fw_iso_resources_free(&dice->tx_resources[i]);
0129 fw_iso_resources_free(&dice->rx_resources[i]);
0130 }
0131 }
0132
0133 static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
0134 struct reg_params *params)
0135 {
0136 __be32 reg;
0137 unsigned int i;
0138
0139 for (i = 0; i < params->count; i++) {
0140 reg = cpu_to_be32((u32)-1);
0141 if (dir == AMDTP_IN_STREAM) {
0142 snd_dice_transaction_write_tx(dice,
0143 params->size * i + TX_ISOCHRONOUS,
0144 ®, sizeof(reg));
0145 } else {
0146 snd_dice_transaction_write_rx(dice,
0147 params->size * i + RX_ISOCHRONOUS,
0148 ®, sizeof(reg));
0149 }
0150 }
0151 }
0152
0153 static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
0154 struct fw_iso_resources *resources, unsigned int rate,
0155 unsigned int pcm_chs, unsigned int midi_ports)
0156 {
0157 bool double_pcm_frames;
0158 unsigned int i;
0159 int err;
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
0170 if (double_pcm_frames) {
0171 rate /= 2;
0172 pcm_chs *= 2;
0173 }
0174
0175 err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
0176 double_pcm_frames);
0177 if (err < 0)
0178 return err;
0179
0180 if (double_pcm_frames) {
0181 pcm_chs /= 2;
0182
0183 for (i = 0; i < pcm_chs; i++) {
0184 amdtp_am824_set_pcm_position(stream, i, i * 2);
0185 amdtp_am824_set_pcm_position(stream, i + pcm_chs,
0186 i * 2 + 1);
0187 }
0188 }
0189
0190 return fw_iso_resources_allocate(resources,
0191 amdtp_stream_get_max_payload(stream),
0192 fw_parent_device(dice->unit)->max_speed);
0193 }
0194
0195 static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
0196 enum amdtp_stream_direction dir,
0197 struct reg_params *params)
0198 {
0199 enum snd_dice_rate_mode mode;
0200 int i;
0201 int err;
0202
0203 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
0204 if (err < 0)
0205 return err;
0206
0207 for (i = 0; i < params->count; ++i) {
0208 __be32 reg[2];
0209 struct amdtp_stream *stream;
0210 struct fw_iso_resources *resources;
0211 unsigned int pcm_cache;
0212 unsigned int pcm_chs;
0213 unsigned int midi_ports;
0214
0215 if (dir == AMDTP_IN_STREAM) {
0216 stream = &dice->tx_stream[i];
0217 resources = &dice->tx_resources[i];
0218
0219 pcm_cache = dice->tx_pcm_chs[i][mode];
0220 err = snd_dice_transaction_read_tx(dice,
0221 params->size * i + TX_NUMBER_AUDIO,
0222 reg, sizeof(reg));
0223 } else {
0224 stream = &dice->rx_stream[i];
0225 resources = &dice->rx_resources[i];
0226
0227 pcm_cache = dice->rx_pcm_chs[i][mode];
0228 err = snd_dice_transaction_read_rx(dice,
0229 params->size * i + RX_NUMBER_AUDIO,
0230 reg, sizeof(reg));
0231 }
0232 if (err < 0)
0233 return err;
0234 pcm_chs = be32_to_cpu(reg[0]);
0235 midi_ports = be32_to_cpu(reg[1]);
0236
0237
0238 if (pcm_chs != pcm_cache) {
0239 dev_info(&dice->unit->device,
0240 "cache mismatch: pcm: %u:%u, midi: %u\n",
0241 pcm_chs, pcm_cache, midi_ports);
0242 return -EPROTO;
0243 }
0244
0245 err = keep_resources(dice, stream, resources, rate, pcm_chs,
0246 midi_ports);
0247 if (err < 0)
0248 return err;
0249 }
0250
0251 return 0;
0252 }
0253
0254 static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
0255 struct reg_params *rx_params)
0256 {
0257 stop_streams(dice, AMDTP_IN_STREAM, tx_params);
0258 stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
0259
0260 snd_dice_transaction_clear_enable(dice);
0261 }
0262
0263 int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
0264 unsigned int events_per_period,
0265 unsigned int events_per_buffer)
0266 {
0267 unsigned int curr_rate;
0268 int err;
0269
0270
0271 err = snd_dice_transaction_get_rate(dice, &curr_rate);
0272 if (err < 0)
0273 return err;
0274 if (rate == 0)
0275 rate = curr_rate;
0276
0277 if (dice->substreams_counter == 0 || curr_rate != rate) {
0278 struct reg_params tx_params, rx_params;
0279
0280 amdtp_domain_stop(&dice->domain);
0281
0282 err = get_register_params(dice, &tx_params, &rx_params);
0283 if (err < 0)
0284 return err;
0285 finish_session(dice, &tx_params, &rx_params);
0286
0287 release_resources(dice);
0288
0289
0290
0291
0292 err = select_clock(dice, rate);
0293 if (err < 0)
0294 return err;
0295
0296
0297
0298 err = get_register_params(dice, &tx_params, &rx_params);
0299 if (err < 0)
0300 return err;
0301
0302 err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
0303 &tx_params);
0304 if (err < 0)
0305 goto error;
0306
0307 err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
0308 &rx_params);
0309 if (err < 0)
0310 goto error;
0311
0312 err = amdtp_domain_set_events_per_period(&dice->domain,
0313 events_per_period, events_per_buffer);
0314 if (err < 0)
0315 goto error;
0316 }
0317
0318 return 0;
0319 error:
0320 release_resources(dice);
0321 return err;
0322 }
0323
0324 static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
0325 unsigned int rate, struct reg_params *params)
0326 {
0327 unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
0328 int i;
0329 int err;
0330
0331 for (i = 0; i < params->count; i++) {
0332 struct amdtp_stream *stream;
0333 struct fw_iso_resources *resources;
0334 __be32 reg;
0335
0336 if (dir == AMDTP_IN_STREAM) {
0337 stream = dice->tx_stream + i;
0338 resources = dice->tx_resources + i;
0339 } else {
0340 stream = dice->rx_stream + i;
0341 resources = dice->rx_resources + i;
0342 }
0343
0344 reg = cpu_to_be32(resources->channel);
0345 if (dir == AMDTP_IN_STREAM) {
0346 err = snd_dice_transaction_write_tx(dice,
0347 params->size * i + TX_ISOCHRONOUS,
0348 ®, sizeof(reg));
0349 } else {
0350 err = snd_dice_transaction_write_rx(dice,
0351 params->size * i + RX_ISOCHRONOUS,
0352 ®, sizeof(reg));
0353 }
0354 if (err < 0)
0355 return err;
0356
0357 if (dir == AMDTP_IN_STREAM) {
0358 reg = cpu_to_be32(max_speed);
0359 err = snd_dice_transaction_write_tx(dice,
0360 params->size * i + TX_SPEED,
0361 ®, sizeof(reg));
0362 if (err < 0)
0363 return err;
0364 }
0365
0366 err = amdtp_domain_add_stream(&dice->domain, stream,
0367 resources->channel, max_speed);
0368 if (err < 0)
0369 return err;
0370 }
0371
0372 return 0;
0373 }
0374
0375
0376
0377
0378
0379
0380 int snd_dice_stream_start_duplex(struct snd_dice *dice)
0381 {
0382 unsigned int generation = dice->rx_resources[0].generation;
0383 struct reg_params tx_params, rx_params;
0384 unsigned int i;
0385 unsigned int rate;
0386 enum snd_dice_rate_mode mode;
0387 int err;
0388
0389 if (dice->substreams_counter == 0)
0390 return -EIO;
0391
0392 err = get_register_params(dice, &tx_params, &rx_params);
0393 if (err < 0)
0394 return err;
0395
0396
0397 for (i = 0; i < MAX_STREAMS; ++i) {
0398 if (amdtp_streaming_error(&dice->tx_stream[i]) ||
0399 amdtp_streaming_error(&dice->rx_stream[i])) {
0400 amdtp_domain_stop(&dice->domain);
0401 finish_session(dice, &tx_params, &rx_params);
0402 break;
0403 }
0404 }
0405
0406 if (generation != fw_parent_device(dice->unit)->card->generation) {
0407 for (i = 0; i < MAX_STREAMS; ++i) {
0408 if (i < tx_params.count)
0409 fw_iso_resources_update(dice->tx_resources + i);
0410 if (i < rx_params.count)
0411 fw_iso_resources_update(dice->rx_resources + i);
0412 }
0413 }
0414
0415
0416 err = snd_dice_transaction_get_rate(dice, &rate);
0417 if (err < 0)
0418 return err;
0419 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
0420 if (err < 0)
0421 return err;
0422 for (i = 0; i < MAX_STREAMS; ++i) {
0423 if (dice->tx_pcm_chs[i][mode] > 0 &&
0424 !amdtp_stream_running(&dice->tx_stream[i]))
0425 break;
0426 if (dice->rx_pcm_chs[i][mode] > 0 &&
0427 !amdtp_stream_running(&dice->rx_stream[i]))
0428 break;
0429 }
0430 if (i < MAX_STREAMS) {
0431
0432 err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
0433 if (err < 0)
0434 goto error;
0435
0436 err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
0437 if (err < 0)
0438 goto error;
0439
0440 err = snd_dice_transaction_set_enable(dice);
0441 if (err < 0) {
0442 dev_err(&dice->unit->device,
0443 "fail to enable interface\n");
0444 goto error;
0445 }
0446
0447
0448
0449
0450
0451 err = amdtp_domain_start(&dice->domain, 0, true, false);
0452 if (err < 0)
0453 goto error;
0454
0455 if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
0456 err = -ETIMEDOUT;
0457 goto error;
0458 }
0459 }
0460
0461 return 0;
0462 error:
0463 amdtp_domain_stop(&dice->domain);
0464 finish_session(dice, &tx_params, &rx_params);
0465 return err;
0466 }
0467
0468
0469
0470
0471
0472
0473 void snd_dice_stream_stop_duplex(struct snd_dice *dice)
0474 {
0475 struct reg_params tx_params, rx_params;
0476
0477 if (dice->substreams_counter == 0) {
0478 if (get_register_params(dice, &tx_params, &rx_params) >= 0)
0479 finish_session(dice, &tx_params, &rx_params);
0480
0481 amdtp_domain_stop(&dice->domain);
0482 release_resources(dice);
0483 }
0484 }
0485
0486 static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
0487 unsigned int index)
0488 {
0489 struct amdtp_stream *stream;
0490 struct fw_iso_resources *resources;
0491 int err;
0492
0493 if (dir == AMDTP_IN_STREAM) {
0494 stream = &dice->tx_stream[index];
0495 resources = &dice->tx_resources[index];
0496 } else {
0497 stream = &dice->rx_stream[index];
0498 resources = &dice->rx_resources[index];
0499 }
0500
0501 err = fw_iso_resources_init(resources, dice->unit);
0502 if (err < 0)
0503 goto end;
0504 resources->channels_mask = 0x00000000ffffffffuLL;
0505
0506 err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
0507 if (err < 0) {
0508 amdtp_stream_destroy(stream);
0509 fw_iso_resources_destroy(resources);
0510 }
0511 end:
0512 return err;
0513 }
0514
0515
0516
0517
0518
0519 static void destroy_stream(struct snd_dice *dice,
0520 enum amdtp_stream_direction dir,
0521 unsigned int index)
0522 {
0523 struct amdtp_stream *stream;
0524 struct fw_iso_resources *resources;
0525
0526 if (dir == AMDTP_IN_STREAM) {
0527 stream = &dice->tx_stream[index];
0528 resources = &dice->tx_resources[index];
0529 } else {
0530 stream = &dice->rx_stream[index];
0531 resources = &dice->rx_resources[index];
0532 }
0533
0534 amdtp_stream_destroy(stream);
0535 fw_iso_resources_destroy(resources);
0536 }
0537
0538 int snd_dice_stream_init_duplex(struct snd_dice *dice)
0539 {
0540 int i, err;
0541
0542 for (i = 0; i < MAX_STREAMS; i++) {
0543 err = init_stream(dice, AMDTP_IN_STREAM, i);
0544 if (err < 0) {
0545 for (; i >= 0; i--)
0546 destroy_stream(dice, AMDTP_IN_STREAM, i);
0547 goto end;
0548 }
0549 }
0550
0551 for (i = 0; i < MAX_STREAMS; i++) {
0552 err = init_stream(dice, AMDTP_OUT_STREAM, i);
0553 if (err < 0) {
0554 for (; i >= 0; i--)
0555 destroy_stream(dice, AMDTP_OUT_STREAM, i);
0556 for (i = 0; i < MAX_STREAMS; i++)
0557 destroy_stream(dice, AMDTP_IN_STREAM, i);
0558 goto end;
0559 }
0560 }
0561
0562 err = amdtp_domain_init(&dice->domain);
0563 if (err < 0) {
0564 for (i = 0; i < MAX_STREAMS; ++i) {
0565 destroy_stream(dice, AMDTP_OUT_STREAM, i);
0566 destroy_stream(dice, AMDTP_IN_STREAM, i);
0567 }
0568 }
0569 end:
0570 return err;
0571 }
0572
0573 void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
0574 {
0575 unsigned int i;
0576
0577 for (i = 0; i < MAX_STREAMS; i++) {
0578 destroy_stream(dice, AMDTP_IN_STREAM, i);
0579 destroy_stream(dice, AMDTP_OUT_STREAM, i);
0580 }
0581
0582 amdtp_domain_destroy(&dice->domain);
0583 }
0584
0585 void snd_dice_stream_update_duplex(struct snd_dice *dice)
0586 {
0587 struct reg_params tx_params, rx_params;
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597 dice->global_enabled = false;
0598
0599 if (get_register_params(dice, &tx_params, &rx_params) == 0) {
0600 amdtp_domain_stop(&dice->domain);
0601
0602 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
0603 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
0604 }
0605 }
0606
0607 int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
0608 {
0609 unsigned int rate;
0610 enum snd_dice_rate_mode mode;
0611 __be32 reg[2];
0612 struct reg_params tx_params, rx_params;
0613 int i;
0614 int err;
0615
0616
0617 err = snd_dice_detect_extension_formats(dice);
0618 if (err >= 0)
0619 return err;
0620
0621
0622
0623
0624
0625 err = snd_dice_transaction_get_rate(dice, &rate);
0626 if (err < 0)
0627 return err;
0628
0629 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
0630 if (err < 0)
0631 return err;
0632
0633
0634
0635
0636
0637
0638 err = select_clock(dice, rate);
0639 if (err < 0)
0640 return err;
0641
0642 err = get_register_params(dice, &tx_params, &rx_params);
0643 if (err < 0)
0644 return err;
0645
0646 for (i = 0; i < tx_params.count; ++i) {
0647 err = snd_dice_transaction_read_tx(dice,
0648 tx_params.size * i + TX_NUMBER_AUDIO,
0649 reg, sizeof(reg));
0650 if (err < 0)
0651 return err;
0652 dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
0653 dice->tx_midi_ports[i] = max_t(unsigned int,
0654 be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
0655 }
0656 for (i = 0; i < rx_params.count; ++i) {
0657 err = snd_dice_transaction_read_rx(dice,
0658 rx_params.size * i + RX_NUMBER_AUDIO,
0659 reg, sizeof(reg));
0660 if (err < 0)
0661 return err;
0662 dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
0663 dice->rx_midi_ports[i] = max_t(unsigned int,
0664 be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
0665 }
0666
0667 return 0;
0668 }
0669
0670 static void dice_lock_changed(struct snd_dice *dice)
0671 {
0672 dice->dev_lock_changed = true;
0673 wake_up(&dice->hwdep_wait);
0674 }
0675
0676 int snd_dice_stream_lock_try(struct snd_dice *dice)
0677 {
0678 int err;
0679
0680 spin_lock_irq(&dice->lock);
0681
0682 if (dice->dev_lock_count < 0) {
0683 err = -EBUSY;
0684 goto out;
0685 }
0686
0687 if (dice->dev_lock_count++ == 0)
0688 dice_lock_changed(dice);
0689 err = 0;
0690 out:
0691 spin_unlock_irq(&dice->lock);
0692 return err;
0693 }
0694
0695 void snd_dice_stream_lock_release(struct snd_dice *dice)
0696 {
0697 spin_lock_irq(&dice->lock);
0698
0699 if (WARN_ON(dice->dev_lock_count <= 0))
0700 goto out;
0701
0702 if (--dice->dev_lock_count == 0)
0703 dice_lock_changed(dice);
0704 out:
0705 spin_unlock_irq(&dice->lock);
0706 }