root/sound/firewire/fireworks/fireworks_pcm.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_multiplier_mode_with_index
  2. snd_efw_get_multiplier_mode
  3. hw_rule_rate
  4. hw_rule_channels
  5. limit_channels
  6. pcm_init_hw_params
  7. pcm_open
  8. pcm_close
  9. pcm_hw_params
  10. pcm_hw_free
  11. pcm_capture_prepare
  12. pcm_playback_prepare
  13. pcm_capture_trigger
  14. pcm_playback_trigger
  15. pcm_capture_pointer
  16. pcm_playback_pointer
  17. pcm_capture_ack
  18. pcm_playback_ack
  19. snd_efw_create_pcm_devices

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * fireworks_pcm.c - a part of driver for Fireworks based devices
   4  *
   5  * Copyright (c) 2009-2010 Clemens Ladisch
   6  * Copyright (c) 2013-2014 Takashi Sakamoto
   7  */
   8 #include "./fireworks.h"
   9 
  10 /*
  11  * NOTE:
  12  * Fireworks changes its AMDTP channels for PCM data according to its sampling
  13  * rate. There are three modes. Here _XX is either _rx or _tx.
  14  *  0:  32.0- 48.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels applied
  15  *  1:  88.2- 96.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_2x applied
  16  *  2: 176.4-192.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_4x applied
  17  *
  18  * The number of PCM channels for analog input and output are always fixed but
  19  * the number of PCM channels for digital input and output are differed.
  20  *
  21  * Additionally, according to "AudioFire Owner's Manual Version 2.2", in some
  22  * model, the number of PCM channels for digital input has more restriction
  23  * depending on which digital interface is selected.
  24  *  - S/PDIF coaxial and optical        : use input 1-2
  25  *  - ADAT optical at 32.0-48.0 kHz     : use input 1-8
  26  *  - ADAT optical at 88.2-96.0 kHz     : use input 1-4 (S/MUX format)
  27  *
  28  * The data in AMDTP channels for blank PCM channels are zero.
  29  */
  30 static const unsigned int freq_table[] = {
  31         /* multiplier mode 0 */
  32         [0] = 32000,
  33         [1] = 44100,
  34         [2] = 48000,
  35         /* multiplier mode 1 */
  36         [3] = 88200,
  37         [4] = 96000,
  38         /* multiplier mode 2 */
  39         [5] = 176400,
  40         [6] = 192000,
  41 };
  42 
  43 static inline unsigned int
  44 get_multiplier_mode_with_index(unsigned int index)
  45 {
  46         return ((int)index - 1) / 2;
  47 }
  48 
  49 int snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode)
  50 {
  51         unsigned int i;
  52 
  53         for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
  54                 if (freq_table[i] == sampling_rate) {
  55                         *mode = get_multiplier_mode_with_index(i);
  56                         return 0;
  57                 }
  58         }
  59 
  60         return -EINVAL;
  61 }
  62 
  63 static int
  64 hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
  65 {
  66         unsigned int *pcm_channels = rule->private;
  67         struct snd_interval *r =
  68                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  69         const struct snd_interval *c =
  70                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  71         struct snd_interval t = {
  72                 .min = UINT_MAX, .max = 0, .integer = 1
  73         };
  74         unsigned int i, mode;
  75 
  76         for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
  77                 mode = get_multiplier_mode_with_index(i);
  78                 if (!snd_interval_test(c, pcm_channels[mode]))
  79                         continue;
  80 
  81                 t.min = min(t.min, freq_table[i]);
  82                 t.max = max(t.max, freq_table[i]);
  83         }
  84 
  85         return snd_interval_refine(r, &t);
  86 }
  87 
  88 static int
  89 hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
  90 {
  91         unsigned int *pcm_channels = rule->private;
  92         struct snd_interval *c =
  93                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  94         const struct snd_interval *r =
  95                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
  96         struct snd_interval t = {
  97                 .min = UINT_MAX, .max = 0, .integer = 1
  98         };
  99         unsigned int i, mode;
 100 
 101         for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
 102                 mode = get_multiplier_mode_with_index(i);
 103                 if (!snd_interval_test(r, freq_table[i]))
 104                         continue;
 105 
 106                 t.min = min(t.min, pcm_channels[mode]);
 107                 t.max = max(t.max, pcm_channels[mode]);
 108         }
 109 
 110         return snd_interval_refine(c, &t);
 111 }
 112 
 113 static void
 114 limit_channels(struct snd_pcm_hardware *hw, unsigned int *pcm_channels)
 115 {
 116         unsigned int i, mode;
 117 
 118         hw->channels_min = UINT_MAX;
 119         hw->channels_max = 0;
 120 
 121         for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
 122                 mode = get_multiplier_mode_with_index(i);
 123                 if (pcm_channels[mode] == 0)
 124                         continue;
 125 
 126                 hw->channels_min = min(hw->channels_min, pcm_channels[mode]);
 127                 hw->channels_max = max(hw->channels_max, pcm_channels[mode]);
 128         }
 129 }
 130 
 131 static int
 132 pcm_init_hw_params(struct snd_efw *efw,
 133                    struct snd_pcm_substream *substream)
 134 {
 135         struct snd_pcm_runtime *runtime = substream->runtime;
 136         struct amdtp_stream *s;
 137         unsigned int *pcm_channels;
 138         int err;
 139 
 140         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 141                 runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
 142                 s = &efw->tx_stream;
 143                 pcm_channels = efw->pcm_capture_channels;
 144         } else {
 145                 runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
 146                 s = &efw->rx_stream;
 147                 pcm_channels = efw->pcm_playback_channels;
 148         }
 149 
 150         /* limit rates */
 151         runtime->hw.rates = efw->supported_sampling_rate,
 152         snd_pcm_limit_hw_rates(runtime);
 153 
 154         limit_channels(&runtime->hw, pcm_channels);
 155 
 156         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 157                                   hw_rule_channels, pcm_channels,
 158                                   SNDRV_PCM_HW_PARAM_RATE, -1);
 159         if (err < 0)
 160                 goto end;
 161 
 162         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 163                                   hw_rule_rate, pcm_channels,
 164                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 165         if (err < 0)
 166                 goto end;
 167 
 168         err = amdtp_am824_add_pcm_hw_constraints(s, runtime);
 169 end:
 170         return err;
 171 }
 172 
 173 static int pcm_open(struct snd_pcm_substream *substream)
 174 {
 175         struct snd_efw *efw = substream->private_data;
 176         unsigned int sampling_rate;
 177         enum snd_efw_clock_source clock_source;
 178         int err;
 179 
 180         err = snd_efw_stream_lock_try(efw);
 181         if (err < 0)
 182                 goto end;
 183 
 184         err = pcm_init_hw_params(efw, substream);
 185         if (err < 0)
 186                 goto err_locked;
 187 
 188         err = snd_efw_command_get_clock_source(efw, &clock_source);
 189         if (err < 0)
 190                 goto err_locked;
 191 
 192         /*
 193          * When source of clock is not internal or any PCM streams are running,
 194          * available sampling rate is limited at current sampling rate.
 195          */
 196         if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) ||
 197             amdtp_stream_pcm_running(&efw->tx_stream) ||
 198             amdtp_stream_pcm_running(&efw->rx_stream)) {
 199                 err = snd_efw_command_get_sampling_rate(efw, &sampling_rate);
 200                 if (err < 0)
 201                         goto err_locked;
 202                 substream->runtime->hw.rate_min = sampling_rate;
 203                 substream->runtime->hw.rate_max = sampling_rate;
 204         }
 205 
 206         snd_pcm_set_sync(substream);
 207 end:
 208         return err;
 209 err_locked:
 210         snd_efw_stream_lock_release(efw);
 211         return err;
 212 }
 213 
 214 static int pcm_close(struct snd_pcm_substream *substream)
 215 {
 216         struct snd_efw *efw = substream->private_data;
 217         snd_efw_stream_lock_release(efw);
 218         return 0;
 219 }
 220 
 221 static int pcm_hw_params(struct snd_pcm_substream *substream,
 222                                  struct snd_pcm_hw_params *hw_params)
 223 {
 224         struct snd_efw *efw = substream->private_data;
 225         int err;
 226 
 227         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 228                                                params_buffer_bytes(hw_params));
 229         if (err < 0)
 230                 return err;
 231 
 232         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 233                 unsigned int rate = params_rate(hw_params);
 234 
 235                 mutex_lock(&efw->mutex);
 236                 err = snd_efw_stream_reserve_duplex(efw, rate);
 237                 if (err >= 0)
 238                         ++efw->substreams_counter;
 239                 mutex_unlock(&efw->mutex);
 240         }
 241 
 242         return err;
 243 }
 244 
 245 static int pcm_hw_free(struct snd_pcm_substream *substream)
 246 {
 247         struct snd_efw *efw = substream->private_data;
 248 
 249         mutex_lock(&efw->mutex);
 250 
 251         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
 252                 --efw->substreams_counter;
 253 
 254         snd_efw_stream_stop_duplex(efw);
 255 
 256         mutex_unlock(&efw->mutex);
 257 
 258         return snd_pcm_lib_free_vmalloc_buffer(substream);
 259 }
 260 
 261 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
 262 {
 263         struct snd_efw *efw = substream->private_data;
 264         int err;
 265 
 266         err = snd_efw_stream_start_duplex(efw);
 267         if (err >= 0)
 268                 amdtp_stream_pcm_prepare(&efw->tx_stream);
 269 
 270         return err;
 271 }
 272 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
 273 {
 274         struct snd_efw *efw = substream->private_data;
 275         int err;
 276 
 277         err = snd_efw_stream_start_duplex(efw);
 278         if (err >= 0)
 279                 amdtp_stream_pcm_prepare(&efw->rx_stream);
 280 
 281         return err;
 282 }
 283 
 284 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
 285 {
 286         struct snd_efw *efw = substream->private_data;
 287 
 288         switch (cmd) {
 289         case SNDRV_PCM_TRIGGER_START:
 290                 amdtp_stream_pcm_trigger(&efw->tx_stream, substream);
 291                 break;
 292         case SNDRV_PCM_TRIGGER_STOP:
 293                 amdtp_stream_pcm_trigger(&efw->tx_stream, NULL);
 294                 break;
 295         default:
 296                 return -EINVAL;
 297         }
 298 
 299         return 0;
 300 }
 301 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 302 {
 303         struct snd_efw *efw = substream->private_data;
 304 
 305         switch (cmd) {
 306         case SNDRV_PCM_TRIGGER_START:
 307                 amdtp_stream_pcm_trigger(&efw->rx_stream, substream);
 308                 break;
 309         case SNDRV_PCM_TRIGGER_STOP:
 310                 amdtp_stream_pcm_trigger(&efw->rx_stream, NULL);
 311                 break;
 312         default:
 313                 return -EINVAL;
 314         }
 315 
 316         return 0;
 317 }
 318 
 319 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
 320 {
 321         struct snd_efw *efw = sbstrm->private_data;
 322         return amdtp_stream_pcm_pointer(&efw->tx_stream);
 323 }
 324 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
 325 {
 326         struct snd_efw *efw = sbstrm->private_data;
 327         return amdtp_stream_pcm_pointer(&efw->rx_stream);
 328 }
 329 
 330 static int pcm_capture_ack(struct snd_pcm_substream *substream)
 331 {
 332         struct snd_efw *efw = substream->private_data;
 333 
 334         return amdtp_stream_pcm_ack(&efw->tx_stream);
 335 }
 336 
 337 static int pcm_playback_ack(struct snd_pcm_substream *substream)
 338 {
 339         struct snd_efw *efw = substream->private_data;
 340 
 341         return amdtp_stream_pcm_ack(&efw->rx_stream);
 342 }
 343 
 344 int snd_efw_create_pcm_devices(struct snd_efw *efw)
 345 {
 346         static const struct snd_pcm_ops capture_ops = {
 347                 .open           = pcm_open,
 348                 .close          = pcm_close,
 349                 .ioctl          = snd_pcm_lib_ioctl,
 350                 .hw_params      = pcm_hw_params,
 351                 .hw_free        = pcm_hw_free,
 352                 .prepare        = pcm_capture_prepare,
 353                 .trigger        = pcm_capture_trigger,
 354                 .pointer        = pcm_capture_pointer,
 355                 .ack            = pcm_capture_ack,
 356                 .page           = snd_pcm_lib_get_vmalloc_page,
 357         };
 358         static const struct snd_pcm_ops playback_ops = {
 359                 .open           = pcm_open,
 360                 .close          = pcm_close,
 361                 .ioctl          = snd_pcm_lib_ioctl,
 362                 .hw_params      = pcm_hw_params,
 363                 .hw_free        = pcm_hw_free,
 364                 .prepare        = pcm_playback_prepare,
 365                 .trigger        = pcm_playback_trigger,
 366                 .pointer        = pcm_playback_pointer,
 367                 .ack            = pcm_playback_ack,
 368                 .page           = snd_pcm_lib_get_vmalloc_page,
 369         };
 370         struct snd_pcm *pcm;
 371         int err;
 372 
 373         err = snd_pcm_new(efw->card, efw->card->driver, 0, 1, 1, &pcm);
 374         if (err < 0)
 375                 goto end;
 376 
 377         pcm->private_data = efw;
 378         snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname);
 379         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
 380         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
 381 end:
 382         return err;
 383 }
 384 

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