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;
 268
 269        err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 270                                               params_buffer_bytes(hw_params));
 271        if (err < 0)
 272                return err;
 273
 274        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 275                unsigned int rate = params_rate(hw_params);
 276                unsigned int events_per_period = params_period_size(hw_params);
 277                unsigned int events_per_buffer = params_buffer_size(hw_params);
 278
 279                mutex_lock(&dice->mutex);
 280                // For double_pcm_frame quirk.
 281                if (rate > 96000) {
 282                        events_per_period /= 2;
 283                        events_per_buffer /= 2;
 284                }
 285                err = snd_dice_stream_reserve_duplex(dice, rate,
 286                                        events_per_period, events_per_buffer);
 287                if (err >= 0)
 288                        ++dice->substreams_counter;
 289                mutex_unlock(&dice->mutex);
 290        }
 291
 292        return err;
 293}
 294
 295static int pcm_hw_free(struct snd_pcm_substream *substream)
 296{
 297        struct snd_dice *dice = substream->private_data;
 298
 299        mutex_lock(&dice->mutex);
 300
 301        if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
 302                --dice->substreams_counter;
 303
 304        snd_dice_stream_stop_duplex(dice);
 305
 306        mutex_unlock(&dice->mutex);
 307
 308        return snd_pcm_lib_free_vmalloc_buffer(substream);
 309}
 310
 311static int capture_prepare(struct snd_pcm_substream *substream)
 312{
 313        struct snd_dice *dice = substream->private_data;
 314        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 315        int err;
 316
 317        mutex_lock(&dice->mutex);
 318        err = snd_dice_stream_start_duplex(dice);
 319        mutex_unlock(&dice->mutex);
 320        if (err >= 0)
 321                amdtp_stream_pcm_prepare(stream);
 322
 323        return 0;
 324}
 325static int playback_prepare(struct snd_pcm_substream *substream)
 326{
 327        struct snd_dice *dice = substream->private_data;
 328        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 329        int err;
 330
 331        mutex_lock(&dice->mutex);
 332        err = snd_dice_stream_start_duplex(dice);
 333        mutex_unlock(&dice->mutex);
 334        if (err >= 0)
 335                amdtp_stream_pcm_prepare(stream);
 336
 337        return err;
 338}
 339
 340static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
 341{
 342        struct snd_dice *dice = substream->private_data;
 343        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 344
 345        switch (cmd) {
 346        case SNDRV_PCM_TRIGGER_START:
 347                amdtp_stream_pcm_trigger(stream, substream);
 348                break;
 349        case SNDRV_PCM_TRIGGER_STOP:
 350                amdtp_stream_pcm_trigger(stream, NULL);
 351                break;
 352        default:
 353                return -EINVAL;
 354        }
 355
 356        return 0;
 357}
 358static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
 359{
 360        struct snd_dice *dice = substream->private_data;
 361        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 362
 363        switch (cmd) {
 364        case SNDRV_PCM_TRIGGER_START:
 365                amdtp_stream_pcm_trigger(stream, substream);
 366                break;
 367        case SNDRV_PCM_TRIGGER_STOP:
 368                amdtp_stream_pcm_trigger(stream, NULL);
 369                break;
 370        default:
 371                return -EINVAL;
 372        }
 373
 374        return 0;
 375}
 376
 377static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
 378{
 379        struct snd_dice *dice = substream->private_data;
 380        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 381
 382        return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
 383}
 384static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
 385{
 386        struct snd_dice *dice = substream->private_data;
 387        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 388
 389        return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
 390}
 391
 392static int capture_ack(struct snd_pcm_substream *substream)
 393{
 394        struct snd_dice *dice = substream->private_data;
 395        struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 396
 397        return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
 398}
 399
 400static int playback_ack(struct snd_pcm_substream *substream)
 401{
 402        struct snd_dice *dice = substream->private_data;
 403        struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 404
 405        return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
 406}
 407
 408int snd_dice_create_pcm(struct snd_dice *dice)
 409{
 410        static const struct snd_pcm_ops capture_ops = {
 411                .open      = pcm_open,
 412                .close     = pcm_close,
 413                .ioctl     = snd_pcm_lib_ioctl,
 414                .hw_params = pcm_hw_params,
 415                .hw_free   = pcm_hw_free,
 416                .prepare   = capture_prepare,
 417                .trigger   = capture_trigger,
 418                .pointer   = capture_pointer,
 419                .ack       = capture_ack,
 420                .page      = snd_pcm_lib_get_vmalloc_page,
 421        };
 422        static const struct snd_pcm_ops playback_ops = {
 423                .open      = pcm_open,
 424                .close     = pcm_close,
 425                .ioctl     = snd_pcm_lib_ioctl,
 426                .hw_params = pcm_hw_params,
 427                .hw_free   = pcm_hw_free,
 428                .prepare   = playback_prepare,
 429                .trigger   = playback_trigger,
 430                .pointer   = playback_pointer,
 431                .ack       = playback_ack,
 432                .page      = snd_pcm_lib_get_vmalloc_page,
 433        };
 434        struct snd_pcm *pcm;
 435        unsigned int capture, playback;
 436        int i, j;
 437        int err;
 438
 439        for (i = 0; i < MAX_STREAMS; i++) {
 440                capture = playback = 0;
 441                for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
 442                        if (dice->tx_pcm_chs[i][j] > 0)
 443                                capture = 1;
 444                        if (dice->rx_pcm_chs[i][j] > 0)
 445                                playback = 1;
 446                }
 447
 448                err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
 449                                  &pcm);
 450                if (err < 0)
 451                        return err;
 452                pcm->private_data = dice;
 453                strcpy(pcm->name, dice->card->shortname);
 454
 455                if (capture > 0)
 456                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 457                                        &capture_ops);
 458
 459                if (playback > 0)
 460                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 461                                        &playback_ops);
 462        }
 463
 464        return 0;
 465}
 466