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 enum snd_tscm_clock clock; 47 unsigned int rate; 48 int err; 49 50 err = snd_tscm_stream_lock_try(tscm); 51 if (err < 0) 52 goto end; 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 (clock != SND_TSCM_CLOCK_INTERNAL || 60 amdtp_stream_pcm_running(&tscm->rx_stream) || 61 amdtp_stream_pcm_running(&tscm->tx_stream)) { 62 err = snd_tscm_stream_get_rate(tscm, &rate); 63 if (err < 0) 64 goto err_locked; 65 substream->runtime->hw.rate_min = rate; 66 substream->runtime->hw.rate_max = rate; 67 } 68 69 snd_pcm_set_sync(substream); 70 end: 71 return err; 72 err_locked: 73 snd_tscm_stream_lock_release(tscm); 74 return err; 75 } 76 77 static int pcm_close(struct snd_pcm_substream *substream) 78 { 79 struct snd_tscm *tscm = substream->private_data; 80 81 snd_tscm_stream_lock_release(tscm); 82 83 return 0; 84 } 85 86 static int pcm_capture_hw_params(struct snd_pcm_substream *substream, 87 struct snd_pcm_hw_params *hw_params) 88 { 89 struct snd_tscm *tscm = substream->private_data; 90 int err; 91 92 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 93 params_buffer_bytes(hw_params)); 94 if (err < 0) 95 return err; 96 97 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 98 mutex_lock(&tscm->mutex); 99 tscm->substreams_counter++; 100 mutex_unlock(&tscm->mutex); 101 } 102 103 return 0; 104 } 105 106 static int pcm_playback_hw_params(struct snd_pcm_substream *substream, 107 struct snd_pcm_hw_params *hw_params) 108 { 109 struct snd_tscm *tscm = substream->private_data; 110 int err; 111 112 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 113 params_buffer_bytes(hw_params)); 114 if (err < 0) 115 return err; 116 117 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 118 mutex_lock(&tscm->mutex); 119 tscm->substreams_counter++; 120 mutex_unlock(&tscm->mutex); 121 } 122 123 return 0; 124 } 125 126 static int pcm_capture_hw_free(struct snd_pcm_substream *substream) 127 { 128 struct snd_tscm *tscm = substream->private_data; 129 130 mutex_lock(&tscm->mutex); 131 132 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 133 tscm->substreams_counter--; 134 135 snd_tscm_stream_stop_duplex(tscm); 136 137 mutex_unlock(&tscm->mutex); 138 139 return snd_pcm_lib_free_vmalloc_buffer(substream); 140 } 141 142 static int pcm_playback_hw_free(struct snd_pcm_substream *substream) 143 { 144 struct snd_tscm *tscm = substream->private_data; 145 146 mutex_lock(&tscm->mutex); 147 148 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 149 tscm->substreams_counter--; 150 151 snd_tscm_stream_stop_duplex(tscm); 152 153 mutex_unlock(&tscm->mutex); 154 155 return snd_pcm_lib_free_vmalloc_buffer(substream); 156 } 157 158 static int pcm_capture_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 mutex_lock(&tscm->mutex); 165 166 err = snd_tscm_stream_start_duplex(tscm, runtime->rate); 167 if (err >= 0) 168 amdtp_stream_pcm_prepare(&tscm->tx_stream); 169 170 mutex_unlock(&tscm->mutex); 171 172 return err; 173 } 174 175 static int pcm_playback_prepare(struct snd_pcm_substream *substream) 176 { 177 struct snd_tscm *tscm = substream->private_data; 178 struct snd_pcm_runtime *runtime = substream->runtime; 179 int err; 180 181 mutex_lock(&tscm->mutex); 182 183 err = snd_tscm_stream_start_duplex(tscm, runtime->rate); 184 if (err >= 0) 185 amdtp_stream_pcm_prepare(&tscm->rx_stream); 186 187 mutex_unlock(&tscm->mutex); 188 189 return err; 190 } 191 192 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 193 { 194 struct snd_tscm *tscm = substream->private_data; 195 196 switch (cmd) { 197 case SNDRV_PCM_TRIGGER_START: 198 amdtp_stream_pcm_trigger(&tscm->tx_stream, substream); 199 break; 200 case SNDRV_PCM_TRIGGER_STOP: 201 amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL); 202 break; 203 default: 204 return -EINVAL; 205 } 206 207 return 0; 208 } 209 210 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 211 { 212 struct snd_tscm *tscm = substream->private_data; 213 214 switch (cmd) { 215 case SNDRV_PCM_TRIGGER_START: 216 amdtp_stream_pcm_trigger(&tscm->rx_stream, substream); 217 break; 218 case SNDRV_PCM_TRIGGER_STOP: 219 amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL); 220 break; 221 default: 222 return -EINVAL; 223 } 224 225 return 0; 226 } 227 228 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) 229 { 230 struct snd_tscm *tscm = sbstrm->private_data; 231 232 return amdtp_stream_pcm_pointer(&tscm->tx_stream); 233 } 234 235 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) 236 { 237 struct snd_tscm *tscm = sbstrm->private_data; 238 239 return amdtp_stream_pcm_pointer(&tscm->rx_stream); 240 } 241 242 static int pcm_capture_ack(struct snd_pcm_substream *substream) 243 { 244 struct snd_tscm *tscm = substream->private_data; 245 246 return amdtp_stream_pcm_ack(&tscm->tx_stream); 247 } 248 249 static int pcm_playback_ack(struct snd_pcm_substream *substream) 250 { 251 struct snd_tscm *tscm = substream->private_data; 252 253 return amdtp_stream_pcm_ack(&tscm->rx_stream); 254 } 255 256 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) 257 { 258 static const struct snd_pcm_ops capture_ops = { 259 .open = pcm_open, 260 .close = pcm_close, 261 .ioctl = snd_pcm_lib_ioctl, 262 .hw_params = pcm_capture_hw_params, 263 .hw_free = pcm_capture_hw_free, 264 .prepare = pcm_capture_prepare, 265 .trigger = pcm_capture_trigger, 266 .pointer = pcm_capture_pointer, 267 .ack = pcm_capture_ack, 268 .page = snd_pcm_lib_get_vmalloc_page, 269 }; 270 static const struct snd_pcm_ops playback_ops = { 271 .open = pcm_open, 272 .close = pcm_close, 273 .ioctl = snd_pcm_lib_ioctl, 274 .hw_params = pcm_playback_hw_params, 275 .hw_free = pcm_playback_hw_free, 276 .prepare = pcm_playback_prepare, 277 .trigger = pcm_playback_trigger, 278 .pointer = pcm_playback_pointer, 279 .ack = pcm_playback_ack, 280 .page = snd_pcm_lib_get_vmalloc_page, 281 }; 282 struct snd_pcm *pcm; 283 int err; 284 285 err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm); 286 if (err < 0) 287 return err; 288 289 pcm->private_data = tscm; 290 snprintf(pcm->name, sizeof(pcm->name), 291 "%s PCM", tscm->card->shortname); 292 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 293 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops); 294 295 return 0; 296 } 297