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

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

DEFINITIONS

This source file includes following definitions.
  1. motu_rate_constraint
  2. motu_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_motu_create_pcm_devices

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * motu-pcm.c - a part of driver for MOTU FireWire series
   4  *
   5  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
   6  */
   7 
   8 #include <sound/pcm_params.h>
   9 #include "motu.h"
  10 
  11 static int motu_rate_constraint(struct snd_pcm_hw_params *params,
  12                                 struct snd_pcm_hw_rule *rule)
  13 {
  14         struct snd_motu_packet_format *formats = rule->private;
  15 
  16         const struct snd_interval *c =
  17                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  18         struct snd_interval *r =
  19                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  20         struct snd_interval rates = {
  21                 .min = UINT_MAX, .max = 0, .integer = 1
  22         };
  23         unsigned int i, pcm_channels, rate, mode;
  24 
  25         for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
  26                 rate = snd_motu_clock_rates[i];
  27                 mode = i / 2;
  28 
  29                 pcm_channels = formats->fixed_part_pcm_chunks[mode] +
  30                                formats->differed_part_pcm_chunks[mode];
  31                 if (!snd_interval_test(c, pcm_channels))
  32                         continue;
  33 
  34                 rates.min = min(rates.min, rate);
  35                 rates.max = max(rates.max, rate);
  36         }
  37 
  38         return snd_interval_refine(r, &rates);
  39 }
  40 
  41 static int motu_channels_constraint(struct snd_pcm_hw_params *params,
  42                                     struct snd_pcm_hw_rule *rule)
  43 {
  44         struct snd_motu_packet_format *formats = rule->private;
  45 
  46         const struct snd_interval *r =
  47                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
  48         struct snd_interval *c =
  49                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  50         struct snd_interval channels = {
  51                 .min = UINT_MAX, .max = 0, .integer = 1
  52         };
  53         unsigned int i, pcm_channels, rate, mode;
  54 
  55         for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
  56                 rate = snd_motu_clock_rates[i];
  57                 mode = i / 2;
  58 
  59                 if (!snd_interval_test(r, rate))
  60                         continue;
  61 
  62                 pcm_channels = formats->fixed_part_pcm_chunks[mode] +
  63                                formats->differed_part_pcm_chunks[mode];
  64                 channels.min = min(channels.min, pcm_channels);
  65                 channels.max = max(channels.max, pcm_channels);
  66         }
  67 
  68         return snd_interval_refine(c, &channels);
  69 }
  70 
  71 static void limit_channels_and_rates(struct snd_motu *motu,
  72                                      struct snd_pcm_runtime *runtime,
  73                                      struct snd_motu_packet_format *formats)
  74 {
  75         struct snd_pcm_hardware *hw = &runtime->hw;
  76         unsigned int i, pcm_channels, rate, mode;
  77 
  78         hw->channels_min = UINT_MAX;
  79         hw->channels_max = 0;
  80 
  81         for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
  82                 rate = snd_motu_clock_rates[i];
  83                 mode = i / 2;
  84 
  85                 pcm_channels = formats->fixed_part_pcm_chunks[mode] +
  86                                formats->differed_part_pcm_chunks[mode];
  87                 if (pcm_channels == 0)
  88                         continue;
  89 
  90                 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
  91                 hw->channels_min = min(hw->channels_min, pcm_channels);
  92                 hw->channels_max = max(hw->channels_max, pcm_channels);
  93         }
  94 
  95         snd_pcm_limit_hw_rates(runtime);
  96 }
  97 
  98 static int init_hw_info(struct snd_motu *motu,
  99                         struct snd_pcm_substream *substream)
 100 {
 101         struct snd_pcm_runtime *runtime = substream->runtime;
 102         struct snd_pcm_hardware *hw = &runtime->hw;
 103         struct amdtp_stream *stream;
 104         struct snd_motu_packet_format *formats;
 105         int err;
 106 
 107         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 108                 hw->formats = SNDRV_PCM_FMTBIT_S32;
 109                 stream = &motu->tx_stream;
 110                 formats = &motu->tx_packet_formats;
 111         } else {
 112                 hw->formats = SNDRV_PCM_FMTBIT_S32;
 113                 stream = &motu->rx_stream;
 114                 formats = &motu->rx_packet_formats;
 115         }
 116 
 117         limit_channels_and_rates(motu, runtime, formats);
 118 
 119         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 120                                   motu_rate_constraint, formats,
 121                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 122         if (err < 0)
 123                 return err;
 124         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 125                                   motu_channels_constraint, formats,
 126                                   SNDRV_PCM_HW_PARAM_RATE, -1);
 127         if (err < 0)
 128                 return err;
 129 
 130         return amdtp_motu_add_pcm_hw_constraints(stream, runtime);
 131 }
 132 
 133 static int pcm_open(struct snd_pcm_substream *substream)
 134 {
 135         struct snd_motu *motu = substream->private_data;
 136         const struct snd_motu_protocol *const protocol = motu->spec->protocol;
 137         enum snd_motu_clock_source src;
 138         unsigned int rate;
 139         int err;
 140 
 141         err = snd_motu_stream_lock_try(motu);
 142         if (err < 0)
 143                 return err;
 144 
 145         mutex_lock(&motu->mutex);
 146 
 147         err = snd_motu_stream_cache_packet_formats(motu);
 148         if (err < 0)
 149                 goto err_locked;
 150 
 151         err = init_hw_info(motu, substream);
 152         if (err < 0)
 153                 goto err_locked;
 154 
 155         /*
 156          * When source of clock is not internal or any PCM streams are running,
 157          * available sampling rate is limited at current sampling rate.
 158          */
 159         err = protocol->get_clock_source(motu, &src);
 160         if (err < 0)
 161                 goto err_locked;
 162         if (src != SND_MOTU_CLOCK_SOURCE_INTERNAL ||
 163             amdtp_stream_pcm_running(&motu->tx_stream) ||
 164             amdtp_stream_pcm_running(&motu->rx_stream)) {
 165                 err = protocol->get_clock_rate(motu, &rate);
 166                 if (err < 0)
 167                         goto err_locked;
 168                 substream->runtime->hw.rate_min = rate;
 169                 substream->runtime->hw.rate_max = rate;
 170         }
 171 
 172         snd_pcm_set_sync(substream);
 173 
 174         mutex_unlock(&motu->mutex);
 175 
 176         return err;
 177 err_locked:
 178         mutex_unlock(&motu->mutex);
 179         snd_motu_stream_lock_release(motu);
 180         return err;
 181 }
 182 
 183 static int pcm_close(struct snd_pcm_substream *substream)
 184 {
 185         struct snd_motu *motu = substream->private_data;
 186 
 187         snd_motu_stream_lock_release(motu);
 188 
 189         return 0;
 190 }
 191 
 192 static int pcm_hw_params(struct snd_pcm_substream *substream,
 193                          struct snd_pcm_hw_params *hw_params)
 194 {
 195         struct snd_motu *motu = substream->private_data;
 196         int err;
 197 
 198         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 199                                                params_buffer_bytes(hw_params));
 200         if (err < 0)
 201                 return err;
 202 
 203         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 204                 unsigned int rate = params_rate(hw_params);
 205 
 206                 mutex_lock(&motu->mutex);
 207                 err = snd_motu_stream_reserve_duplex(motu, rate);
 208                 if (err >= 0)
 209                         ++motu->substreams_counter;
 210                 mutex_unlock(&motu->mutex);
 211         }
 212 
 213         return err;
 214 }
 215 
 216 static int pcm_hw_free(struct snd_pcm_substream *substream)
 217 {
 218         struct snd_motu *motu = substream->private_data;
 219 
 220         mutex_lock(&motu->mutex);
 221 
 222         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
 223                 --motu->substreams_counter;
 224 
 225         snd_motu_stream_stop_duplex(motu);
 226 
 227         mutex_unlock(&motu->mutex);
 228 
 229         return snd_pcm_lib_free_vmalloc_buffer(substream);
 230 }
 231 
 232 static int capture_prepare(struct snd_pcm_substream *substream)
 233 {
 234         struct snd_motu *motu = substream->private_data;
 235         int err;
 236 
 237         mutex_lock(&motu->mutex);
 238         err = snd_motu_stream_start_duplex(motu);
 239         mutex_unlock(&motu->mutex);
 240         if (err >= 0)
 241                 amdtp_stream_pcm_prepare(&motu->tx_stream);
 242 
 243         return 0;
 244 }
 245 static int playback_prepare(struct snd_pcm_substream *substream)
 246 {
 247         struct snd_motu *motu = substream->private_data;
 248         int err;
 249 
 250         mutex_lock(&motu->mutex);
 251         err = snd_motu_stream_start_duplex(motu);
 252         mutex_unlock(&motu->mutex);
 253         if (err >= 0)
 254                 amdtp_stream_pcm_prepare(&motu->rx_stream);
 255 
 256         return err;
 257 }
 258 
 259 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
 260 {
 261         struct snd_motu *motu = substream->private_data;
 262 
 263         switch (cmd) {
 264         case SNDRV_PCM_TRIGGER_START:
 265                 amdtp_stream_pcm_trigger(&motu->tx_stream, substream);
 266                 break;
 267         case SNDRV_PCM_TRIGGER_STOP:
 268                 amdtp_stream_pcm_trigger(&motu->tx_stream, NULL);
 269                 break;
 270         default:
 271                 return -EINVAL;
 272         }
 273 
 274         return 0;
 275 }
 276 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
 277 {
 278         struct snd_motu *motu = substream->private_data;
 279 
 280         switch (cmd) {
 281         case SNDRV_PCM_TRIGGER_START:
 282                 amdtp_stream_pcm_trigger(&motu->rx_stream, substream);
 283                 break;
 284         case SNDRV_PCM_TRIGGER_STOP:
 285                 amdtp_stream_pcm_trigger(&motu->rx_stream, NULL);
 286                 break;
 287         default:
 288                 return -EINVAL;
 289         }
 290 
 291         return 0;
 292 }
 293 
 294 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
 295 {
 296         struct snd_motu *motu = substream->private_data;
 297 
 298         return amdtp_stream_pcm_pointer(&motu->tx_stream);
 299 }
 300 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
 301 {
 302         struct snd_motu *motu = substream->private_data;
 303 
 304         return amdtp_stream_pcm_pointer(&motu->rx_stream);
 305 }
 306 
 307 static int capture_ack(struct snd_pcm_substream *substream)
 308 {
 309         struct snd_motu *motu = substream->private_data;
 310 
 311         return amdtp_stream_pcm_ack(&motu->tx_stream);
 312 }
 313 
 314 static int playback_ack(struct snd_pcm_substream *substream)
 315 {
 316         struct snd_motu *motu = substream->private_data;
 317 
 318         return amdtp_stream_pcm_ack(&motu->rx_stream);
 319 }
 320 
 321 int snd_motu_create_pcm_devices(struct snd_motu *motu)
 322 {
 323         static const struct snd_pcm_ops capture_ops = {
 324                 .open      = pcm_open,
 325                 .close     = pcm_close,
 326                 .ioctl     = snd_pcm_lib_ioctl,
 327                 .hw_params = pcm_hw_params,
 328                 .hw_free   = pcm_hw_free,
 329                 .prepare   = capture_prepare,
 330                 .trigger   = capture_trigger,
 331                 .pointer   = capture_pointer,
 332                 .ack       = capture_ack,
 333                 .page      = snd_pcm_lib_get_vmalloc_page,
 334         };
 335         static const struct snd_pcm_ops playback_ops = {
 336                 .open      = pcm_open,
 337                 .close     = pcm_close,
 338                 .ioctl     = snd_pcm_lib_ioctl,
 339                 .hw_params = pcm_hw_params,
 340                 .hw_free   = pcm_hw_free,
 341                 .prepare   = playback_prepare,
 342                 .trigger   = playback_trigger,
 343                 .pointer   = playback_pointer,
 344                 .ack       = playback_ack,
 345                 .page      = snd_pcm_lib_get_vmalloc_page,
 346         };
 347         struct snd_pcm *pcm;
 348         int err;
 349 
 350         err = snd_pcm_new(motu->card, motu->card->driver, 0, 1, 1, &pcm);
 351         if (err < 0)
 352                 return err;
 353         pcm->private_data = motu;
 354         strcpy(pcm->name, motu->card->shortname);
 355 
 356         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
 357         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
 358 
 359         return 0;
 360 }

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