linux/sound/firewire/dice/dice-pcm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * dice_pcm.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
  11static int dice_rate_constraint(struct snd_pcm_hw_params *params,
  12                                struct snd_pcm_hw_rule *rule)
  13{
  14        struct snd_pcm_substream *substream = rule->private;
  15        struct snd_dice *dice = substream->private_data;
  16        unsigned int index = substream->pcm->device;
  17
  18        const struct snd_interval *c =
  19                hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  20        struct snd_interval *r =
  21                hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  22        struct snd_interval rates = {
  23                .min = UINT_MAX, .max = 0, .integer = 1
  24        };
  25        unsigned int *pcm_channels;
  26        enum snd_dice_rate_mode mode;
  27        unsigned int i, rate;
  28
  29        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  30                pcm_channels = dice->tx_pcm_chs[index];
  31        else
  32                pcm_channels = dice->rx_pcm_chs[index];
  33
  34        for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
  35                rate = snd_dice_rates[i];
  36                if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
  37                        continue;
  38
  39                if (!snd_interval_test(c, pcm_channels[mode]))
  40                        continue;
  41
  42                rates.min = min(rates.min, rate);
  43                rates.max = max(rates.max, rate);
  44        }
  45
  46        return snd_interval_refine(r, &rates);
  47}
  48
  49static int dice_channels_constraint(struct snd_pcm_hw_params *params,
  50                                    struct snd_pcm_hw_rule *rule)
  51{
  52        struct snd_pcm_substream *substream = rule->private;
  53        struct snd_dice *dice = substream->private_data;
  54        unsigned int index = substream->pcm->device;
  55
  56        const struct snd_interval *r =
  57                hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
  58        struct snd_interval *c =
  59                hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  60        struct snd_interval channels = {
  61                .min = UINT_MAX, .max = 0, .integer = 1
  62        };
  63        unsigned int *pcm_channels;
  64        enum snd_dice_rate_mode mode;
  65        unsigned int i, rate;
  66
  67        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  68                pcm_channels = dice->tx_pcm_chs[index];
  69        else
  70                pcm_channels = dice->rx_pcm_chs[index];
  71
  72        for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
  73                rate = snd_dice_rates[i];
  74                if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
  75                        continue;
  76
  77                if (!snd_interval_test(r, rate))
  78                        continue;
  79
  80                channels.min = min(channels.min, pcm_channels[mode]);
  81                channels.max = max(channels.max, pcm_channels[mode]);
  82        }
  83
  84        return snd_interval_refine(c, &channels);
  85}
  86
  87static int limit_channels_and_rates(struct snd_dice *dice,
  88                                    struct snd_pcm_runtime *runtime,
  89                                    enum amdtp_stream_direction dir,
  90                                    unsigned int index)
  91{
  92        struct snd_pcm_hardware *hw = &runtime->hw;
  93        unsigned int *pcm_channels;
  94        unsigned int i;
  95
  96        if (dir == AMDTP_IN_STREAM)
  97                pcm_channels = dice->tx_pcm_chs[index];
  98        else
  99                pcm_channels = dice->rx_pcm_chs[index];
 100
 101        hw->channels_min = UINT_MAX;
 102        hw->channels_max = 0;
 103
 104        for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
 105                enum snd_dice_rate_mode mode;
 106                unsigned int rate, channels;
 107
 108                rate = snd_dice_rates[i];
 109                if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
 110                        continue;
 111                hw->rates |= snd_pcm_rate_to_rate_bit(rate);
 112
 113                channels = pcm_channels[mode];
 114                if (channels == 0)
 115                        continue;
 116                hw->channels_min = min(hw->channels_min, channels);
 117                hw->channels_max = max(hw->channels_max, channels);
 118        }
 119
 120        snd_pcm_limit_hw_rates(runtime);
 121
 122        return 0;
 123}
 124
 125static int init_hw_info(struct snd_dice *dice,
 126                        struct snd_pcm_substream *substream)
 127{
 128        struct snd_pcm_runtime *runtime = substream->runtime;
 129        struct snd_pcm_hardware *hw = &runtime->hw;
 130        unsigned int index = substream->pcm->device;
 131        enum amdtp_stream_direction dir;
 132        struct amdtp_stream *stream;
 133        int err;
 134
 135        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 136                hw->formats = AM824_IN_PCM_FORMAT_BITS;
 137                dir = AMDTP_IN_STREAM;
 138                stream = &dice->tx_stream[index];
 139        } else {
 140                hw->formats = AM824_OUT_PCM_FORMAT_BITS;
 141                dir = AMDTP_OUT_STREAM;
 142                stream = &dice->rx_stream[index];
 143        }
 144
 145        err = limit_channels_and_rates(dice, substream->runtime, dir,
 146                                       index);
 147        if (err < 0)
 148                return err;
 149
 150        err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 151                                  dice_rate_constraint, substream,
 152                                  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 153        if (err < 0)
 154                return err;
 155        err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 156                                  dice_channels_constraint, substream,
 157                                  SNDRV_PCM_HW_PARAM_RATE, -1);
 158        if (err < 0)
 159                return err;
 160
 161        return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
 162}
 163
 164static int pcm_open(struct snd_pcm_substream *substream)
 165{
 166        struct snd_dice *dice = substream->private_data;
 167        struct amdtp_domain *d = &dice->domain;
 168        unsigned int source;
 169        bool internal;
 170        int err;
 171
 172        err = snd_dice_stream_lock_try(dice);
 173        if (err < 0)
 174                return err;
 175
 176        err = init_hw_info(dice, substream);
 177        if (err < 0)
 178                goto err_locked;
 179
 180        err = snd_dice_transaction_get_clock_source(dice, &source);
 181        if (err < 0)
 182                goto err_locked;
 183        switch (source) {
 184        case CLOCK_SOURCE_AES1:
 185        case CLOCK_SOURCE_AES2:
 186        case CLOCK_SOURCE_AES3:
 187        case CLOCK_SOURCE_AES4:
 188        case CLOCK_SOURCE_AES_ANY:
 189        case CLOCK_SOURCE_ADAT:
 190        case CLOCK_SOURCE_TDIF:
 191        case CLOCK_SOURCE_WC:
 192                internal = false;
 193                break;
 194        default:
 195                internal = true;
 196                break;
 197        }
 198
 199        mutex_lock(&dice->mutex);
 200
 201        // When source of clock is not internal or any stream is reserved for
 202        // transmission of PCM frames, the available sampling rate is limited
 203        // at current one.
 204        if (!internal ||
 205            (dice->substreams_counter > 0 && d->events_per_period > 0)) {
 206                unsigned int frames_per_period = d->events_per_period;
 207                unsigned int frames_per_buffer = d->events_per_buffer;
 208                unsigned int rate;
 209
 210                err = snd_dice_transaction_get_rate(dice, &rate);
 211                if (err < 0) {
 212                        mutex_unlock(&dice->mutex);
 213                        goto err_locked;
 214                }
 215
 216                substream->runtime->hw.rate_min = rate;
 217                substream->runtime->hw.rate_max = rate;
 218
 219                if (frames_per_period > 0) {
 220                        // For double_pcm_frame quirk.
 221                        if (rate > 96000) {
 222                                frames_per_period *= 2;
 223                                frames_per_buffer *= 2;
 224                        }
 225
 226                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
 227                                        SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
 228                                        frames_per_period, frames_per_period);
 229                        if (err < 0) {
 230                                mutex_unlock(&dice->mutex);
 231                                goto err_locked;
 232                        }
 233
 234                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
 235                                        SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
 236                                        frames_per_buffer, frames_per_buffer);
 237                        if (err < 0) {
 238                                mutex_unlock(&dice->mutex);
 239                                goto err_locked;
 240                        }
 241                }
 242        }
 243
 244        mutex_unlock(&dice->mutex);
 245
 246        snd_pcm_set_sync(substream);
 247
 248        return 0;
 249err_locked:
 250        snd_dice_stream_lock_release(dice);
 251        return err;
 252}
 253
 254static int pcm_close(struct snd_pcm_substream *substream)
 255{
 256        struct snd_dice *dice = substream->private_data;
 257
 258        snd_dice_stream_lock_release(dice);
 259
 260        return 0;
 261}
 262
 263static int pcm_hw_params(struct snd_pcm_substream *substream,
 264                         struct snd_pcm_hw_params *hw_params)
 265{
 266        struct snd_dice *dice = substream->private_data;
 267        int err = 0;
 268
 269        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 270                unsigned int rate = params_rate(hw_params);
 271                unsigned int events_per_period = params_period_size(hw_params);
 272                unsigned int events_per_buffer = params_buffer_size(hw_params);
 273
 274                mutex_lock(&dice->mutex);
 275                // For double_pcm_frame quirk.
 276                if (rate > 96000) {
 277                        events_per_period /= 2;
 278                        events_per_buffer /= 2;
 279                }
 280                err = snd_dice_stream_reserve_duplex(dice, rate,
 281                                        events_per_period, events_per_buffer);
 282                if (err >= 0)
 283                        ++dice->substreams_counter;
 284                mutex_unlock(&dice->mutex);
 285        }
 286
 287        return err;
 288}
 289
 290static int pcm_hw_free(struct snd_pcm_substream *substream)
 291{
 292        struct snd_dice *dice = substream->private_data;
 293
 294        mutex_lock(&dice->mutex);
 295
 296        if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
 297                --dice->substreams_counter;
 298
 299        snd_dice_stream_stop_duplex(dice);
 300
 301        mutex_unlock(&dice->mutex);
 302
 303        return 0;
 304}
 305
 306static int capture_prepare(struct snd_pcm_substream *substream)
 307{
 308        struct snd_dice *dice = substream->private_data;
 309        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 310        int err;
 311
 312        mutex_lock(&dice->mutex);
 313        err = snd_dice_stream_start_duplex(dice);
 314        mutex_unlock(&dice->mutex);
 315        if (err >= 0)
 316                amdtp_stream_pcm_prepare(stream);
 317
 318        return 0;
 319}
 320static int playback_prepare(struct snd_pcm_substream *substream)
 321{
 322        struct snd_dice *dice = substream->private_data;
 323        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 324        int err;
 325
 326        mutex_lock(&dice->mutex);
 327        err = snd_dice_stream_start_duplex(dice);
 328        mutex_unlock(&dice->mutex);
 329        if (err >= 0)
 330                amdtp_stream_pcm_prepare(stream);
 331
 332        return err;
 333}
 334
 335static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
 336{
 337        struct snd_dice *dice = substream->private_data;
 338        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 339
 340        switch (cmd) {
 341        case SNDRV_PCM_TRIGGER_START:
 342                amdtp_stream_pcm_trigger(stream, substream);
 343                break;
 344        case SNDRV_PCM_TRIGGER_STOP:
 345                amdtp_stream_pcm_trigger(stream, NULL);
 346                break;
 347        default:
 348                return -EINVAL;
 349        }
 350
 351        return 0;
 352}
 353static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
 354{
 355        struct snd_dice *dice = substream->private_data;
 356        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 357
 358        switch (cmd) {
 359        case SNDRV_PCM_TRIGGER_START:
 360                amdtp_stream_pcm_trigger(stream, substream);
 361                break;
 362        case SNDRV_PCM_TRIGGER_STOP:
 363                amdtp_stream_pcm_trigger(stream, NULL);
 364                break;
 365        default:
 366                return -EINVAL;
 367        }
 368
 369        return 0;
 370}
 371
 372static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
 373{
 374        struct snd_dice *dice = substream->private_data;
 375        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 376
 377        return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
 378}
 379static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
 380{
 381        struct snd_dice *dice = substream->private_data;
 382        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 383
 384        return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
 385}
 386
 387static int capture_ack(struct snd_pcm_substream *substream)
 388{
 389        struct snd_dice *dice = substream->private_data;
 390        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 391
 392        return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
 393}
 394
 395static int playback_ack(struct snd_pcm_substream *substream)
 396{
 397        struct snd_dice *dice = substream->private_data;
 398        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 399
 400        return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
 401}
 402
 403int snd_dice_create_pcm(struct snd_dice *dice)
 404{
 405        static const struct snd_pcm_ops capture_ops = {
 406                .open      = pcm_open,
 407                .close     = pcm_close,
 408                .hw_params = pcm_hw_params,
 409                .hw_free   = pcm_hw_free,
 410                .prepare   = capture_prepare,
 411                .trigger   = capture_trigger,
 412                .pointer   = capture_pointer,
 413                .ack       = capture_ack,
 414        };
 415        static const struct snd_pcm_ops playback_ops = {
 416                .open      = pcm_open,
 417                .close     = pcm_close,
 418                .hw_params = pcm_hw_params,
 419                .hw_free   = pcm_hw_free,
 420                .prepare   = playback_prepare,
 421                .trigger   = playback_trigger,
 422                .pointer   = playback_pointer,
 423                .ack       = playback_ack,
 424        };
 425        struct snd_pcm *pcm;
 426        unsigned int capture, playback;
 427        int i, j;
 428        int err;
 429
 430        for (i = 0; i < MAX_STREAMS; i++) {
 431                capture = playback = 0;
 432                for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
 433                        if (dice->tx_pcm_chs[i][j] > 0)
 434                                capture = 1;
 435                        if (dice->rx_pcm_chs[i][j] > 0)
 436                                playback = 1;
 437                }
 438
 439                err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
 440                                  &pcm);
 441                if (err < 0)
 442                        return err;
 443                pcm->private_data = dice;
 444                strcpy(pcm->name, dice->card->shortname);
 445
 446                if (capture > 0)
 447                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 448                                        &capture_ops);
 449
 450                if (playback > 0)
 451                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 452                                        &playback_ops);
 453
 454                snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
 455                                               NULL, 0, 0);
 456        }
 457
 458        return 0;
 459}
 460