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

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

DEFINITIONS

This source file includes following definitions.
  1. dice_rate_constraint
  2. dice_channels_constraint
  3. limit_channels_and_rates
  4. init_hw_info
  5. pcm_open
  6. pcm_close
  7. pcm_hw_params
  8. pcm_hw_free
  9. capture_prepare
  10. playback_prepare
  11. capture_trigger
  12. playback_trigger
  13. capture_pointer
  14. playback_pointer
  15. capture_ack
  16. playback_ack
  17. snd_dice_create_pcm

   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 
  11 static 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 
  49 static 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 
  87 static 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 
 125 static 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 
 164 static int pcm_open(struct snd_pcm_substream *substream)
 165 {
 166         struct snd_dice *dice = substream->private_data;
 167         unsigned int source;
 168         bool internal;
 169         int err;
 170 
 171         err = snd_dice_stream_lock_try(dice);
 172         if (err < 0)
 173                 goto end;
 174 
 175         err = init_hw_info(dice, substream);
 176         if (err < 0)
 177                 goto err_locked;
 178 
 179         err = snd_dice_transaction_get_clock_source(dice, &source);
 180         if (err < 0)
 181                 goto err_locked;
 182         switch (source) {
 183         case CLOCK_SOURCE_AES1:
 184         case CLOCK_SOURCE_AES2:
 185         case CLOCK_SOURCE_AES3:
 186         case CLOCK_SOURCE_AES4:
 187         case CLOCK_SOURCE_AES_ANY:
 188         case CLOCK_SOURCE_ADAT:
 189         case CLOCK_SOURCE_TDIF:
 190         case CLOCK_SOURCE_WC:
 191                 internal = false;
 192                 break;
 193         default:
 194                 internal = true;
 195                 break;
 196         }
 197 
 198         /*
 199          * When source of clock is not internal or any PCM streams are running,
 200          * available sampling rate is limited at current sampling rate.
 201          */
 202         if (!internal ||
 203             amdtp_stream_pcm_running(&dice->tx_stream[0]) ||
 204             amdtp_stream_pcm_running(&dice->tx_stream[1]) ||
 205             amdtp_stream_pcm_running(&dice->rx_stream[0]) ||
 206             amdtp_stream_pcm_running(&dice->rx_stream[1])) {
 207                 unsigned int rate;
 208 
 209                 err = snd_dice_transaction_get_rate(dice, &rate);
 210                 if (err < 0)
 211                         goto err_locked;
 212                 substream->runtime->hw.rate_min = rate;
 213                 substream->runtime->hw.rate_max = rate;
 214         }
 215 
 216         snd_pcm_set_sync(substream);
 217 end:
 218         return err;
 219 err_locked:
 220         snd_dice_stream_lock_release(dice);
 221         return err;
 222 }
 223 
 224 static int pcm_close(struct snd_pcm_substream *substream)
 225 {
 226         struct snd_dice *dice = substream->private_data;
 227 
 228         snd_dice_stream_lock_release(dice);
 229 
 230         return 0;
 231 }
 232 
 233 static int pcm_hw_params(struct snd_pcm_substream *substream,
 234                          struct snd_pcm_hw_params *hw_params)
 235 {
 236         struct snd_dice *dice = substream->private_data;
 237         int err;
 238 
 239         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 240                                                params_buffer_bytes(hw_params));
 241         if (err < 0)
 242                 return err;
 243 
 244         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 245                 unsigned int rate = params_rate(hw_params);
 246 
 247                 mutex_lock(&dice->mutex);
 248                 err = snd_dice_stream_reserve_duplex(dice, rate);
 249                 if (err >= 0)
 250                         ++dice->substreams_counter;
 251                 mutex_unlock(&dice->mutex);
 252         }
 253 
 254         return err;
 255 }
 256 
 257 static int pcm_hw_free(struct snd_pcm_substream *substream)
 258 {
 259         struct snd_dice *dice = substream->private_data;
 260 
 261         mutex_lock(&dice->mutex);
 262 
 263         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
 264                 --dice->substreams_counter;
 265 
 266         snd_dice_stream_stop_duplex(dice);
 267 
 268         mutex_unlock(&dice->mutex);
 269 
 270         return snd_pcm_lib_free_vmalloc_buffer(substream);
 271 }
 272 
 273 static int capture_prepare(struct snd_pcm_substream *substream)
 274 {
 275         struct snd_dice *dice = substream->private_data;
 276         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 277         int err;
 278 
 279         mutex_lock(&dice->mutex);
 280         err = snd_dice_stream_start_duplex(dice);
 281         mutex_unlock(&dice->mutex);
 282         if (err >= 0)
 283                 amdtp_stream_pcm_prepare(stream);
 284 
 285         return 0;
 286 }
 287 static int playback_prepare(struct snd_pcm_substream *substream)
 288 {
 289         struct snd_dice *dice = substream->private_data;
 290         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 291         int err;
 292 
 293         mutex_lock(&dice->mutex);
 294         err = snd_dice_stream_start_duplex(dice);
 295         mutex_unlock(&dice->mutex);
 296         if (err >= 0)
 297                 amdtp_stream_pcm_prepare(stream);
 298 
 299         return err;
 300 }
 301 
 302 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
 303 {
 304         struct snd_dice *dice = substream->private_data;
 305         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 306 
 307         switch (cmd) {
 308         case SNDRV_PCM_TRIGGER_START:
 309                 amdtp_stream_pcm_trigger(stream, substream);
 310                 break;
 311         case SNDRV_PCM_TRIGGER_STOP:
 312                 amdtp_stream_pcm_trigger(stream, NULL);
 313                 break;
 314         default:
 315                 return -EINVAL;
 316         }
 317 
 318         return 0;
 319 }
 320 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
 321 {
 322         struct snd_dice *dice = substream->private_data;
 323         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 324 
 325         switch (cmd) {
 326         case SNDRV_PCM_TRIGGER_START:
 327                 amdtp_stream_pcm_trigger(stream, substream);
 328                 break;
 329         case SNDRV_PCM_TRIGGER_STOP:
 330                 amdtp_stream_pcm_trigger(stream, NULL);
 331                 break;
 332         default:
 333                 return -EINVAL;
 334         }
 335 
 336         return 0;
 337 }
 338 
 339 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
 340 {
 341         struct snd_dice *dice = substream->private_data;
 342         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 343 
 344         return amdtp_stream_pcm_pointer(stream);
 345 }
 346 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
 347 {
 348         struct snd_dice *dice = substream->private_data;
 349         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 350 
 351         return amdtp_stream_pcm_pointer(stream);
 352 }
 353 
 354 static int capture_ack(struct snd_pcm_substream *substream)
 355 {
 356         struct snd_dice *dice = substream->private_data;
 357         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
 358 
 359         return amdtp_stream_pcm_ack(stream);
 360 }
 361 
 362 static int playback_ack(struct snd_pcm_substream *substream)
 363 {
 364         struct snd_dice *dice = substream->private_data;
 365         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
 366 
 367         return amdtp_stream_pcm_ack(stream);
 368 }
 369 
 370 int snd_dice_create_pcm(struct snd_dice *dice)
 371 {
 372         static const struct snd_pcm_ops capture_ops = {
 373                 .open      = pcm_open,
 374                 .close     = pcm_close,
 375                 .ioctl     = snd_pcm_lib_ioctl,
 376                 .hw_params = pcm_hw_params,
 377                 .hw_free   = pcm_hw_free,
 378                 .prepare   = capture_prepare,
 379                 .trigger   = capture_trigger,
 380                 .pointer   = capture_pointer,
 381                 .ack       = capture_ack,
 382                 .page      = snd_pcm_lib_get_vmalloc_page,
 383         };
 384         static const struct snd_pcm_ops playback_ops = {
 385                 .open      = pcm_open,
 386                 .close     = pcm_close,
 387                 .ioctl     = snd_pcm_lib_ioctl,
 388                 .hw_params = pcm_hw_params,
 389                 .hw_free   = pcm_hw_free,
 390                 .prepare   = playback_prepare,
 391                 .trigger   = playback_trigger,
 392                 .pointer   = playback_pointer,
 393                 .ack       = playback_ack,
 394                 .page      = snd_pcm_lib_get_vmalloc_page,
 395         };
 396         struct snd_pcm *pcm;
 397         unsigned int capture, playback;
 398         int i, j;
 399         int err;
 400 
 401         for (i = 0; i < MAX_STREAMS; i++) {
 402                 capture = playback = 0;
 403                 for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
 404                         if (dice->tx_pcm_chs[i][j] > 0)
 405                                 capture = 1;
 406                         if (dice->rx_pcm_chs[i][j] > 0)
 407                                 playback = 1;
 408                 }
 409 
 410                 err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
 411                                   &pcm);
 412                 if (err < 0)
 413                         return err;
 414                 pcm->private_data = dice;
 415                 strcpy(pcm->name, dice->card->shortname);
 416 
 417                 if (capture > 0)
 418                         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 419                                         &capture_ops);
 420 
 421                 if (playback > 0)
 422                         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 423                                         &playback_ops);
 424         }
 425 
 426         return 0;
 427 }

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