Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * tascam-pcm.c - a part of driver for TASCAM FireWire series
0004  *
0005  * Copyright (c) 2015 Takashi Sakamoto
0006  */
0007 
0008 #include "tascam.h"
0009 
0010 static int pcm_init_hw_params(struct snd_tscm *tscm,
0011                   struct snd_pcm_substream *substream)
0012 {
0013     struct snd_pcm_runtime *runtime = substream->runtime;
0014     struct snd_pcm_hardware *hw = &runtime->hw;
0015     struct amdtp_stream *stream;
0016     unsigned int pcm_channels;
0017 
0018     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
0019         runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
0020         stream = &tscm->tx_stream;
0021         pcm_channels = tscm->spec->pcm_capture_analog_channels;
0022     } else {
0023         runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
0024         stream = &tscm->rx_stream;
0025         pcm_channels = tscm->spec->pcm_playback_analog_channels;
0026     }
0027 
0028     if (tscm->spec->has_adat)
0029         pcm_channels += 8;
0030     if (tscm->spec->has_spdif)
0031         pcm_channels += 2;
0032     runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels;
0033 
0034     hw->rates = SNDRV_PCM_RATE_44100 |
0035             SNDRV_PCM_RATE_48000 |
0036             SNDRV_PCM_RATE_88200 |
0037             SNDRV_PCM_RATE_96000;
0038     snd_pcm_limit_hw_rates(runtime);
0039 
0040     return amdtp_tscm_add_pcm_hw_constraints(stream, runtime);
0041 }
0042 
0043 static int pcm_open(struct snd_pcm_substream *substream)
0044 {
0045     struct snd_tscm *tscm = substream->private_data;
0046     struct amdtp_domain *d = &tscm->domain;
0047     enum snd_tscm_clock clock;
0048     int err;
0049 
0050     err = snd_tscm_stream_lock_try(tscm);
0051     if (err < 0)
0052         return err;
0053 
0054     err = pcm_init_hw_params(tscm, substream);
0055     if (err < 0)
0056         goto err_locked;
0057 
0058     err = snd_tscm_stream_get_clock(tscm, &clock);
0059     if (err < 0)
0060         goto err_locked;
0061 
0062     mutex_lock(&tscm->mutex);
0063 
0064     // When source of clock is not internal or any stream is reserved for
0065     // transmission of PCM frames, the available sampling rate is limited
0066     // at current one.
0067     if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) {
0068         unsigned int frames_per_period = d->events_per_period;
0069         unsigned int frames_per_buffer = d->events_per_buffer;
0070         unsigned int rate;
0071 
0072         err = snd_tscm_stream_get_rate(tscm, &rate);
0073         if (err < 0) {
0074             mutex_unlock(&tscm->mutex);
0075             goto err_locked;
0076         }
0077         substream->runtime->hw.rate_min = rate;
0078         substream->runtime->hw.rate_max = rate;
0079 
0080         err = snd_pcm_hw_constraint_minmax(substream->runtime,
0081                     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
0082                     frames_per_period, frames_per_period);
0083         if (err < 0) {
0084             mutex_unlock(&tscm->mutex);
0085             goto err_locked;
0086         }
0087 
0088         err = snd_pcm_hw_constraint_minmax(substream->runtime,
0089                     SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
0090                     frames_per_buffer, frames_per_buffer);
0091         if (err < 0) {
0092             mutex_unlock(&tscm->mutex);
0093             goto err_locked;
0094         }
0095     }
0096 
0097     mutex_unlock(&tscm->mutex);
0098 
0099     snd_pcm_set_sync(substream);
0100 
0101     return 0;
0102 err_locked:
0103     snd_tscm_stream_lock_release(tscm);
0104     return err;
0105 }
0106 
0107 static int pcm_close(struct snd_pcm_substream *substream)
0108 {
0109     struct snd_tscm *tscm = substream->private_data;
0110 
0111     snd_tscm_stream_lock_release(tscm);
0112 
0113     return 0;
0114 }
0115 
0116 static int pcm_hw_params(struct snd_pcm_substream *substream,
0117              struct snd_pcm_hw_params *hw_params)
0118 {
0119     struct snd_tscm *tscm = substream->private_data;
0120     int err = 0;
0121 
0122     if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
0123         unsigned int rate = params_rate(hw_params);
0124         unsigned int frames_per_period = params_period_size(hw_params);
0125         unsigned int frames_per_buffer = params_buffer_size(hw_params);
0126 
0127         mutex_lock(&tscm->mutex);
0128         err = snd_tscm_stream_reserve_duplex(tscm, rate,
0129                     frames_per_period, frames_per_buffer);
0130         if (err >= 0)
0131             ++tscm->substreams_counter;
0132         mutex_unlock(&tscm->mutex);
0133     }
0134 
0135     return err;
0136 }
0137 
0138 static int pcm_hw_free(struct snd_pcm_substream *substream)
0139 {
0140     struct snd_tscm *tscm = substream->private_data;
0141 
0142     mutex_lock(&tscm->mutex);
0143 
0144     if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
0145         --tscm->substreams_counter;
0146 
0147     snd_tscm_stream_stop_duplex(tscm);
0148 
0149     mutex_unlock(&tscm->mutex);
0150 
0151     return 0;
0152 }
0153 
0154 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
0155 {
0156     struct snd_tscm *tscm = substream->private_data;
0157     struct snd_pcm_runtime *runtime = substream->runtime;
0158     int err;
0159 
0160     mutex_lock(&tscm->mutex);
0161 
0162     err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
0163     if (err >= 0)
0164         amdtp_stream_pcm_prepare(&tscm->tx_stream);
0165 
0166     mutex_unlock(&tscm->mutex);
0167 
0168     return err;
0169 }
0170 
0171 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
0172 {
0173     struct snd_tscm *tscm = substream->private_data;
0174     struct snd_pcm_runtime *runtime = substream->runtime;
0175     int err;
0176 
0177     mutex_lock(&tscm->mutex);
0178 
0179     err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
0180     if (err >= 0)
0181         amdtp_stream_pcm_prepare(&tscm->rx_stream);
0182 
0183     mutex_unlock(&tscm->mutex);
0184 
0185     return err;
0186 }
0187 
0188 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
0189 {
0190     struct snd_tscm *tscm = substream->private_data;
0191 
0192     switch (cmd) {
0193     case SNDRV_PCM_TRIGGER_START:
0194         amdtp_stream_pcm_trigger(&tscm->tx_stream, substream);
0195         break;
0196     case SNDRV_PCM_TRIGGER_STOP:
0197         amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL);
0198         break;
0199     default:
0200         return -EINVAL;
0201     }
0202 
0203     return 0;
0204 }
0205 
0206 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
0207 {
0208     struct snd_tscm *tscm = substream->private_data;
0209 
0210     switch (cmd) {
0211     case SNDRV_PCM_TRIGGER_START:
0212         amdtp_stream_pcm_trigger(&tscm->rx_stream, substream);
0213         break;
0214     case SNDRV_PCM_TRIGGER_STOP:
0215         amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL);
0216         break;
0217     default:
0218         return -EINVAL;
0219     }
0220 
0221     return 0;
0222 }
0223 
0224 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
0225 {
0226     struct snd_tscm *tscm = sbstrm->private_data;
0227 
0228     return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->tx_stream);
0229 }
0230 
0231 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
0232 {
0233     struct snd_tscm *tscm = sbstrm->private_data;
0234 
0235     return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->rx_stream);
0236 }
0237 
0238 static int pcm_capture_ack(struct snd_pcm_substream *substream)
0239 {
0240     struct snd_tscm *tscm = substream->private_data;
0241 
0242     return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->tx_stream);
0243 }
0244 
0245 static int pcm_playback_ack(struct snd_pcm_substream *substream)
0246 {
0247     struct snd_tscm *tscm = substream->private_data;
0248 
0249     return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->rx_stream);
0250 }
0251 
0252 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
0253 {
0254     static const struct snd_pcm_ops capture_ops = {
0255         .open       = pcm_open,
0256         .close      = pcm_close,
0257         .hw_params  = pcm_hw_params,
0258         .hw_free    = pcm_hw_free,
0259         .prepare    = pcm_capture_prepare,
0260         .trigger    = pcm_capture_trigger,
0261         .pointer    = pcm_capture_pointer,
0262         .ack        = pcm_capture_ack,
0263     };
0264     static const struct snd_pcm_ops playback_ops = {
0265         .open       = pcm_open,
0266         .close      = pcm_close,
0267         .hw_params  = pcm_hw_params,
0268         .hw_free    = pcm_hw_free,
0269         .prepare    = pcm_playback_prepare,
0270         .trigger    = pcm_playback_trigger,
0271         .pointer    = pcm_playback_pointer,
0272         .ack        = pcm_playback_ack,
0273     };
0274     struct snd_pcm *pcm;
0275     int err;
0276 
0277     err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm);
0278     if (err < 0)
0279         return err;
0280 
0281     pcm->private_data = tscm;
0282     snprintf(pcm->name, sizeof(pcm->name),
0283          "%s PCM", tscm->card->shortname);
0284     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
0285     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
0286     snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
0287 
0288     return 0;
0289 }