Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * motu-pcm.c - a part of driver for MOTU FireWire series
0004  *
0005  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
0006  */
0007 
0008 #include <sound/pcm_params.h>
0009 #include "motu.h"
0010 
0011 static int motu_rate_constraint(struct snd_pcm_hw_params *params,
0012                 struct snd_pcm_hw_rule *rule)
0013 {
0014     struct snd_motu_packet_format *formats = rule->private;
0015 
0016     const struct snd_interval *c =
0017         hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
0018     struct snd_interval *r =
0019         hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
0020     struct snd_interval rates = {
0021         .min = UINT_MAX, .max = 0, .integer = 1
0022     };
0023     unsigned int i, pcm_channels, rate, mode;
0024 
0025     for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
0026         rate = snd_motu_clock_rates[i];
0027         mode = i / 2;
0028 
0029         pcm_channels = formats->pcm_chunks[mode];
0030         if (!snd_interval_test(c, pcm_channels))
0031             continue;
0032 
0033         rates.min = min(rates.min, rate);
0034         rates.max = max(rates.max, rate);
0035     }
0036 
0037     return snd_interval_refine(r, &rates);
0038 }
0039 
0040 static int motu_channels_constraint(struct snd_pcm_hw_params *params,
0041                     struct snd_pcm_hw_rule *rule)
0042 {
0043     struct snd_motu_packet_format *formats = rule->private;
0044 
0045     const struct snd_interval *r =
0046         hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
0047     struct snd_interval *c =
0048         hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
0049     struct snd_interval channels = {
0050         .min = UINT_MAX, .max = 0, .integer = 1
0051     };
0052     unsigned int i, pcm_channels, rate, mode;
0053 
0054     for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
0055         rate = snd_motu_clock_rates[i];
0056         mode = i / 2;
0057 
0058         if (!snd_interval_test(r, rate))
0059             continue;
0060 
0061         pcm_channels = formats->pcm_chunks[mode];
0062         channels.min = min(channels.min, pcm_channels);
0063         channels.max = max(channels.max, pcm_channels);
0064     }
0065 
0066     return snd_interval_refine(c, &channels);
0067 }
0068 
0069 static void limit_channels_and_rates(struct snd_motu *motu,
0070                      struct snd_pcm_runtime *runtime,
0071                      struct snd_motu_packet_format *formats)
0072 {
0073     struct snd_pcm_hardware *hw = &runtime->hw;
0074     unsigned int i, pcm_channels, rate, mode;
0075 
0076     hw->channels_min = UINT_MAX;
0077     hw->channels_max = 0;
0078 
0079     for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
0080         rate = snd_motu_clock_rates[i];
0081         mode = i / 2;
0082 
0083         pcm_channels = formats->pcm_chunks[mode];
0084         if (pcm_channels == 0)
0085             continue;
0086 
0087         hw->rates |= snd_pcm_rate_to_rate_bit(rate);
0088         hw->channels_min = min(hw->channels_min, pcm_channels);
0089         hw->channels_max = max(hw->channels_max, pcm_channels);
0090     }
0091 
0092     snd_pcm_limit_hw_rates(runtime);
0093 }
0094 
0095 static int init_hw_info(struct snd_motu *motu,
0096             struct snd_pcm_substream *substream)
0097 {
0098     struct snd_pcm_runtime *runtime = substream->runtime;
0099     struct snd_pcm_hardware *hw = &runtime->hw;
0100     struct amdtp_stream *stream;
0101     struct snd_motu_packet_format *formats;
0102     int err;
0103 
0104     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
0105         hw->formats = SNDRV_PCM_FMTBIT_S32;
0106         stream = &motu->tx_stream;
0107         formats = &motu->tx_packet_formats;
0108     } else {
0109         hw->formats = SNDRV_PCM_FMTBIT_S32;
0110         stream = &motu->rx_stream;
0111         formats = &motu->rx_packet_formats;
0112     }
0113 
0114     limit_channels_and_rates(motu, runtime, formats);
0115 
0116     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
0117                   motu_rate_constraint, formats,
0118                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
0119     if (err < 0)
0120         return err;
0121     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
0122                   motu_channels_constraint, formats,
0123                   SNDRV_PCM_HW_PARAM_RATE, -1);
0124     if (err < 0)
0125         return err;
0126 
0127     return amdtp_motu_add_pcm_hw_constraints(stream, runtime);
0128 }
0129 
0130 static int pcm_open(struct snd_pcm_substream *substream)
0131 {
0132     struct snd_motu *motu = substream->private_data;
0133     struct amdtp_domain *d = &motu->domain;
0134     enum snd_motu_clock_source src;
0135     int err;
0136 
0137     err = snd_motu_stream_lock_try(motu);
0138     if (err < 0)
0139         return err;
0140 
0141     mutex_lock(&motu->mutex);
0142 
0143     err = snd_motu_stream_cache_packet_formats(motu);
0144     if (err < 0)
0145         goto err_locked;
0146 
0147     err = init_hw_info(motu, substream);
0148     if (err < 0)
0149         goto err_locked;
0150 
0151     err = snd_motu_protocol_get_clock_source(motu, &src);
0152     if (err < 0)
0153         goto err_locked;
0154 
0155     // When source of clock is not internal or any stream is reserved for
0156     // transmission of PCM frames, the available sampling rate is limited
0157     // at current one.
0158     if ((src != SND_MOTU_CLOCK_SOURCE_INTERNAL &&
0159          src != SND_MOTU_CLOCK_SOURCE_SPH) ||
0160         (motu->substreams_counter > 0 && d->events_per_period > 0)) {
0161         unsigned int frames_per_period = d->events_per_period;
0162         unsigned int frames_per_buffer = d->events_per_buffer;
0163         unsigned int rate;
0164 
0165         err = snd_motu_protocol_get_clock_rate(motu, &rate);
0166         if (err < 0)
0167             goto err_locked;
0168 
0169         substream->runtime->hw.rate_min = rate;
0170         substream->runtime->hw.rate_max = rate;
0171 
0172         if (frames_per_period > 0) {
0173             err = snd_pcm_hw_constraint_minmax(substream->runtime,
0174                     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
0175                     frames_per_period, frames_per_period);
0176             if (err < 0)
0177                 goto err_locked;
0178 
0179             err = snd_pcm_hw_constraint_minmax(substream->runtime,
0180                     SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
0181                     frames_per_buffer, frames_per_buffer);
0182             if (err < 0)
0183                 goto err_locked;
0184         }
0185     }
0186 
0187     snd_pcm_set_sync(substream);
0188 
0189     mutex_unlock(&motu->mutex);
0190 
0191     return 0;
0192 err_locked:
0193     mutex_unlock(&motu->mutex);
0194     snd_motu_stream_lock_release(motu);
0195     return err;
0196 }
0197 
0198 static int pcm_close(struct snd_pcm_substream *substream)
0199 {
0200     struct snd_motu *motu = substream->private_data;
0201 
0202     snd_motu_stream_lock_release(motu);
0203 
0204     return 0;
0205 }
0206 
0207 static int pcm_hw_params(struct snd_pcm_substream *substream,
0208              struct snd_pcm_hw_params *hw_params)
0209 {
0210     struct snd_motu *motu = substream->private_data;
0211     int err = 0;
0212 
0213     if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
0214         unsigned int rate = params_rate(hw_params);
0215         unsigned int frames_per_period = params_period_size(hw_params);
0216         unsigned int frames_per_buffer = params_buffer_size(hw_params);
0217 
0218         mutex_lock(&motu->mutex);
0219         err = snd_motu_stream_reserve_duplex(motu, rate,
0220                     frames_per_period, frames_per_buffer);
0221         if (err >= 0)
0222             ++motu->substreams_counter;
0223         mutex_unlock(&motu->mutex);
0224     }
0225 
0226     return err;
0227 }
0228 
0229 static int pcm_hw_free(struct snd_pcm_substream *substream)
0230 {
0231     struct snd_motu *motu = substream->private_data;
0232 
0233     mutex_lock(&motu->mutex);
0234 
0235     if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
0236         --motu->substreams_counter;
0237 
0238     snd_motu_stream_stop_duplex(motu);
0239 
0240     mutex_unlock(&motu->mutex);
0241 
0242     return 0;
0243 }
0244 
0245 static int capture_prepare(struct snd_pcm_substream *substream)
0246 {
0247     struct snd_motu *motu = substream->private_data;
0248     int err;
0249 
0250     mutex_lock(&motu->mutex);
0251     err = snd_motu_stream_start_duplex(motu);
0252     mutex_unlock(&motu->mutex);
0253     if (err >= 0)
0254         amdtp_stream_pcm_prepare(&motu->tx_stream);
0255 
0256     return 0;
0257 }
0258 static int playback_prepare(struct snd_pcm_substream *substream)
0259 {
0260     struct snd_motu *motu = substream->private_data;
0261     int err;
0262 
0263     mutex_lock(&motu->mutex);
0264     err = snd_motu_stream_start_duplex(motu);
0265     mutex_unlock(&motu->mutex);
0266     if (err >= 0)
0267         amdtp_stream_pcm_prepare(&motu->rx_stream);
0268 
0269     return err;
0270 }
0271 
0272 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
0273 {
0274     struct snd_motu *motu = substream->private_data;
0275 
0276     switch (cmd) {
0277     case SNDRV_PCM_TRIGGER_START:
0278         amdtp_stream_pcm_trigger(&motu->tx_stream, substream);
0279         break;
0280     case SNDRV_PCM_TRIGGER_STOP:
0281         amdtp_stream_pcm_trigger(&motu->tx_stream, NULL);
0282         break;
0283     default:
0284         return -EINVAL;
0285     }
0286 
0287     return 0;
0288 }
0289 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
0290 {
0291     struct snd_motu *motu = substream->private_data;
0292 
0293     switch (cmd) {
0294     case SNDRV_PCM_TRIGGER_START:
0295         amdtp_stream_pcm_trigger(&motu->rx_stream, substream);
0296         break;
0297     case SNDRV_PCM_TRIGGER_STOP:
0298         amdtp_stream_pcm_trigger(&motu->rx_stream, NULL);
0299         break;
0300     default:
0301         return -EINVAL;
0302     }
0303 
0304     return 0;
0305 }
0306 
0307 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
0308 {
0309     struct snd_motu *motu = substream->private_data;
0310 
0311     return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->tx_stream);
0312 }
0313 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
0314 {
0315     struct snd_motu *motu = substream->private_data;
0316 
0317     return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->rx_stream);
0318 }
0319 
0320 static int capture_ack(struct snd_pcm_substream *substream)
0321 {
0322     struct snd_motu *motu = substream->private_data;
0323 
0324     return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->tx_stream);
0325 }
0326 
0327 static int playback_ack(struct snd_pcm_substream *substream)
0328 {
0329     struct snd_motu *motu = substream->private_data;
0330 
0331     return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->rx_stream);
0332 }
0333 
0334 int snd_motu_create_pcm_devices(struct snd_motu *motu)
0335 {
0336     static const struct snd_pcm_ops capture_ops = {
0337         .open      = pcm_open,
0338         .close     = pcm_close,
0339         .hw_params = pcm_hw_params,
0340         .hw_free   = pcm_hw_free,
0341         .prepare   = capture_prepare,
0342         .trigger   = capture_trigger,
0343         .pointer   = capture_pointer,
0344         .ack       = capture_ack,
0345     };
0346     static const struct snd_pcm_ops playback_ops = {
0347         .open      = pcm_open,
0348         .close     = pcm_close,
0349         .hw_params = pcm_hw_params,
0350         .hw_free   = pcm_hw_free,
0351         .prepare   = playback_prepare,
0352         .trigger   = playback_trigger,
0353         .pointer   = playback_pointer,
0354         .ack       = playback_ack,
0355     };
0356     struct snd_pcm *pcm;
0357     int err;
0358 
0359     err = snd_pcm_new(motu->card, motu->card->driver, 0, 1, 1, &pcm);
0360     if (err < 0)
0361         return err;
0362     pcm->private_data = motu;
0363     strcpy(pcm->name, motu->card->shortname);
0364 
0365     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
0366     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
0367     snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
0368 
0369     return 0;
0370 }