1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * tascam-pcm.c - a part of driver for TASCAM FireWire series 4 * 5 * Copyright (c) 2015 Takashi Sakamoto 6 */ 7 8 #include "tascam.h" 9 10 static int pcm_init_hw_params(struct snd_tscm *tscm, 11 struct snd_pcm_substream *substream) 12 { 13 struct snd_pcm_runtime *runtime = substream->runtime; 14 struct snd_pcm_hardware *hw = &runtime->hw; 15 struct amdtp_stream *stream; 16 unsigned int pcm_channels; 17 18 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 19 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; 20 stream = &tscm->tx_stream; 21 pcm_channels = tscm->spec->pcm_capture_analog_channels; 22 } else { 23 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; 24 stream = &tscm->rx_stream; 25 pcm_channels = tscm->spec->pcm_playback_analog_channels; 26 } 27 28 if (tscm->spec->has_adat) 29 pcm_channels += 8; 30 if (tscm->spec->has_spdif) 31 pcm_channels += 2; 32 runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels; 33 34 hw->rates = SNDRV_PCM_RATE_44100 | 35 SNDRV_PCM_RATE_48000 | 36 SNDRV_PCM_RATE_88200 | 37 SNDRV_PCM_RATE_96000; 38 snd_pcm_limit_hw_rates(runtime); 39 40 return amdtp_tscm_add_pcm_hw_constraints(stream, runtime); 41 } 42 43 static int pcm_open(struct snd_pcm_substream *substream) 44 { 45 struct snd_tscm *tscm = substream->private_data; 46 struct amdtp_domain *d = &tscm->domain; 47 enum snd_tscm_clock clock; 48 int err; 49 50 err = snd_tscm_stream_lock_try(tscm); 51 if (err < 0) 52 return err; 53 54 err = pcm_init_hw_params(tscm, substream); 55 if (err < 0) 56 goto err_locked; 57 58 err = snd_tscm_stream_get_clock(tscm, &clock); 59 if (err < 0) 60 goto err_locked; 61 62 scoped_guard(mutex, &tscm->mutex) { 63 // When source of clock is not internal or any stream is reserved for 64 // transmission of PCM frames, the available sampling rate is limited 65 // at current one. 66 if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) { 67 unsigned int frames_per_period = d->events_per_period; 68 unsigned int frames_per_buffer = d->events_per_buffer; 69 unsigned int rate; 70 71 err = snd_tscm_stream_get_rate(tscm, &rate); 72 if (err < 0) 73 goto err_locked; 74 substream->runtime->hw.rate_min = rate; 75 substream->runtime->hw.rate_max = rate; 76 77 err = snd_pcm_hw_constraint_minmax(substream->runtime, 78 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 79 frames_per_period, frames_per_period); 80 if (err < 0) 81 goto err_locked; 82 83 err = snd_pcm_hw_constraint_minmax(substream->runtime, 84 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 85 frames_per_buffer, frames_per_buffer); 86 if (err < 0) 87 goto err_locked; 88 } 89 } 90 91 snd_pcm_set_sync(substream); 92 93 return 0; 94 err_locked: 95 snd_tscm_stream_lock_release(tscm); 96 return err; 97 } 98 99 static int pcm_close(struct snd_pcm_substream *substream) 100 { 101 struct snd_tscm *tscm = substream->private_data; 102 103 snd_tscm_stream_lock_release(tscm); 104 105 return 0; 106 } 107 108 static int pcm_hw_params(struct snd_pcm_substream *substream, 109 struct snd_pcm_hw_params *hw_params) 110 { 111 struct snd_tscm *tscm = substream->private_data; 112 int err = 0; 113 114 if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { 115 unsigned int rate = params_rate(hw_params); 116 unsigned int frames_per_period = params_period_size(hw_params); 117 unsigned int frames_per_buffer = params_buffer_size(hw_params); 118 119 guard(mutex)(&tscm->mutex); 120 err = snd_tscm_stream_reserve_duplex(tscm, rate, 121 frames_per_period, frames_per_buffer); 122 if (err >= 0) 123 ++tscm->substreams_counter; 124 } 125 126 return err; 127 } 128 129 static int pcm_hw_free(struct snd_pcm_substream *substream) 130 { 131 struct snd_tscm *tscm = substream->private_data; 132 133 guard(mutex)(&tscm->mutex); 134 135 if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) 136 --tscm->substreams_counter; 137 138 snd_tscm_stream_stop_duplex(tscm); 139 140 return 0; 141 } 142 143 static int pcm_capture_prepare(struct snd_pcm_substream *substream) 144 { 145 struct snd_tscm *tscm = substream->private_data; 146 struct snd_pcm_runtime *runtime = substream->runtime; 147 int err; 148 149 guard(mutex)(&tscm->mutex); 150 151 err = snd_tscm_stream_start_duplex(tscm, runtime->rate); 152 if (err >= 0) 153 amdtp_stream_pcm_prepare(&tscm->tx_stream); 154 155 return err; 156 } 157 158 static int pcm_playback_prepare(struct snd_pcm_substream *substream) 159 { 160 struct snd_tscm *tscm = substream->private_data; 161 struct snd_pcm_runtime *runtime = substream->runtime; 162 int err; 163 164 guard(mutex)(&tscm->mutex); 165 166 err = snd_tscm_stream_start_duplex(tscm, runtime->rate); 167 if (err >= 0) 168 amdtp_stream_pcm_prepare(&tscm->rx_stream); 169 170 return err; 171 } 172 173 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 174 { 175 struct snd_tscm *tscm = substream->private_data; 176 177 switch (cmd) { 178 case SNDRV_PCM_TRIGGER_START: 179 amdtp_stream_pcm_trigger(&tscm->tx_stream, substream); 180 break; 181 case SNDRV_PCM_TRIGGER_STOP: 182 amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL); 183 break; 184 default: 185 return -EINVAL; 186 } 187 188 return 0; 189 } 190 191 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 192 { 193 struct snd_tscm *tscm = substream->private_data; 194 195 switch (cmd) { 196 case SNDRV_PCM_TRIGGER_START: 197 amdtp_stream_pcm_trigger(&tscm->rx_stream, substream); 198 break; 199 case SNDRV_PCM_TRIGGER_STOP: 200 amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL); 201 break; 202 default: 203 return -EINVAL; 204 } 205 206 return 0; 207 } 208 209 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) 210 { 211 struct snd_tscm *tscm = sbstrm->private_data; 212 213 return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->tx_stream); 214 } 215 216 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) 217 { 218 struct snd_tscm *tscm = sbstrm->private_data; 219 220 return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->rx_stream); 221 } 222 223 static int pcm_capture_ack(struct snd_pcm_substream *substream) 224 { 225 struct snd_tscm *tscm = substream->private_data; 226 227 return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->tx_stream); 228 } 229 230 static int pcm_playback_ack(struct snd_pcm_substream *substream) 231 { 232 struct snd_tscm *tscm = substream->private_data; 233 234 return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->rx_stream); 235 } 236 237 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) 238 { 239 static const struct snd_pcm_ops capture_ops = { 240 .open = pcm_open, 241 .close = pcm_close, 242 .hw_params = pcm_hw_params, 243 .hw_free = pcm_hw_free, 244 .prepare = pcm_capture_prepare, 245 .trigger = pcm_capture_trigger, 246 .pointer = pcm_capture_pointer, 247 .ack = pcm_capture_ack, 248 }; 249 static const struct snd_pcm_ops playback_ops = { 250 .open = pcm_open, 251 .close = pcm_close, 252 .hw_params = pcm_hw_params, 253 .hw_free = pcm_hw_free, 254 .prepare = pcm_playback_prepare, 255 .trigger = pcm_playback_trigger, 256 .pointer = pcm_playback_pointer, 257 .ack = pcm_playback_ack, 258 }; 259 struct snd_pcm *pcm; 260 int err; 261 262 err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm); 263 if (err < 0) 264 return err; 265 266 pcm->private_data = tscm; 267 pcm->nonatomic = true; 268 snprintf(pcm->name, sizeof(pcm->name), 269 "%s PCM", tscm->card->shortname); 270 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 271 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops); 272 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); 273 274 return 0; 275 } 276