root/sound/firewire/dice/dice-stream.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_dice_stream_get_rate_mode
  2. ensure_phase_lock
  3. get_register_params
  4. release_resources
  5. stop_streams
  6. keep_resources
  7. keep_dual_resources
  8. finish_session
  9. snd_dice_stream_reserve_duplex
  10. start_streams
  11. snd_dice_stream_start_duplex
  12. snd_dice_stream_stop_duplex
  13. init_stream
  14. destroy_stream
  15. snd_dice_stream_init_duplex
  16. snd_dice_stream_destroy_duplex
  17. snd_dice_stream_update_duplex
  18. snd_dice_stream_detect_current_formats
  19. dice_lock_changed
  20. snd_dice_stream_lock_try
  21. snd_dice_stream_lock_release

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

/* [<][>][^][v][top][bottom][index][help] */