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