Back to home page

OSCL-LXR

 
 

    


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