1 /* 2 * digi00x-pcm.c - a part of driver for Digidesign Digi 002/003 family 3 * 4 * Copyright (c) 2014-2015 Takashi Sakamoto 5 * 6 * Licensed under the terms of the GNU General Public License, version 2. 7 */ 8 9 #include "digi00x.h" 10 11 static int hw_rule_rate(struct snd_pcm_hw_params *params, 12 struct snd_pcm_hw_rule *rule) 13 { 14 struct snd_interval *r = 15 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 16 const struct snd_interval *c = 17 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); 18 struct snd_interval t = { 19 .min = UINT_MAX, .max = 0, .integer = 1, 20 }; 21 unsigned int i; 22 23 for (i = 0; i < SND_DG00X_RATE_COUNT; i++) { 24 if (!snd_interval_test(c, 25 snd_dg00x_stream_pcm_channels[i])) 26 continue; 27 28 t.min = min(t.min, snd_dg00x_stream_rates[i]); 29 t.max = max(t.max, snd_dg00x_stream_rates[i]); 30 } 31 32 return snd_interval_refine(r, &t); 33 } 34 35 static int hw_rule_channels(struct snd_pcm_hw_params *params, 36 struct snd_pcm_hw_rule *rule) 37 { 38 struct snd_interval *c = 39 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 40 const struct snd_interval *r = 41 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); 42 struct snd_interval t = { 43 .min = UINT_MAX, .max = 0, .integer = 1, 44 }; 45 unsigned int i; 46 47 for (i = 0; i < SND_DG00X_RATE_COUNT; i++) { 48 if (!snd_interval_test(r, snd_dg00x_stream_rates[i])) 49 continue; 50 51 t.min = min(t.min, snd_dg00x_stream_pcm_channels[i]); 52 t.max = max(t.max, snd_dg00x_stream_pcm_channels[i]); 53 } 54 55 return snd_interval_refine(c, &t); 56 } 57 58 static int pcm_init_hw_params(struct snd_dg00x *dg00x, 59 struct snd_pcm_substream *substream) 60 { 61 static const struct snd_pcm_hardware hardware = { 62 .info = SNDRV_PCM_INFO_BATCH | 63 SNDRV_PCM_INFO_BLOCK_TRANSFER | 64 SNDRV_PCM_INFO_INTERLEAVED | 65 SNDRV_PCM_INFO_JOINT_DUPLEX | 66 SNDRV_PCM_INFO_MMAP | 67 SNDRV_PCM_INFO_MMAP_VALID, 68 .rates = SNDRV_PCM_RATE_44100 | 69 SNDRV_PCM_RATE_48000 | 70 SNDRV_PCM_RATE_88200 | 71 SNDRV_PCM_RATE_96000, 72 .rate_min = 44100, 73 .rate_max = 96000, 74 .channels_min = 10, 75 .channels_max = 18, 76 .period_bytes_min = 4 * 18, 77 .period_bytes_max = 4 * 18 * 2048, 78 .buffer_bytes_max = 4 * 18 * 2048 * 2, 79 .periods_min = 2, 80 .periods_max = UINT_MAX, 81 }; 82 struct amdtp_stream *s; 83 int err; 84 85 substream->runtime->hw = hardware; 86 87 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 88 substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; 89 s = &dg00x->tx_stream; 90 } else { 91 substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16 | 92 SNDRV_PCM_FMTBIT_S32; 93 s = &dg00x->rx_stream; 94 } 95 96 err = snd_pcm_hw_rule_add(substream->runtime, 0, 97 SNDRV_PCM_HW_PARAM_CHANNELS, 98 hw_rule_channels, NULL, 99 SNDRV_PCM_HW_PARAM_RATE, -1); 100 if (err < 0) 101 return err; 102 103 err = snd_pcm_hw_rule_add(substream->runtime, 0, 104 SNDRV_PCM_HW_PARAM_RATE, 105 hw_rule_rate, NULL, 106 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 107 if (err < 0) 108 return err; 109 110 return amdtp_dot_add_pcm_hw_constraints(s, substream->runtime); 111 } 112 113 static int pcm_open(struct snd_pcm_substream *substream) 114 { 115 struct snd_dg00x *dg00x = substream->private_data; 116 enum snd_dg00x_clock clock; 117 bool detect; 118 unsigned int rate; 119 int err; 120 121 err = snd_dg00x_stream_lock_try(dg00x); 122 if (err < 0) 123 goto end; 124 125 err = pcm_init_hw_params(dg00x, substream); 126 if (err < 0) 127 goto err_locked; 128 129 /* Check current clock source. */ 130 err = snd_dg00x_stream_get_clock(dg00x, &clock); 131 if (err < 0) 132 goto err_locked; 133 if (clock != SND_DG00X_CLOCK_INTERNAL) { 134 err = snd_dg00x_stream_check_external_clock(dg00x, &detect); 135 if (err < 0) 136 goto err_locked; 137 if (!detect) { 138 err = -EBUSY; 139 goto err_locked; 140 } 141 } 142 143 if ((clock != SND_DG00X_CLOCK_INTERNAL) || 144 amdtp_stream_pcm_running(&dg00x->rx_stream) || 145 amdtp_stream_pcm_running(&dg00x->tx_stream)) { 146 err = snd_dg00x_stream_get_external_rate(dg00x, &rate); 147 if (err < 0) 148 goto err_locked; 149 substream->runtime->hw.rate_min = rate; 150 substream->runtime->hw.rate_max = rate; 151 } 152 153 snd_pcm_set_sync(substream); 154 end: 155 return err; 156 err_locked: 157 snd_dg00x_stream_lock_release(dg00x); 158 return err; 159 } 160 161 static int pcm_close(struct snd_pcm_substream *substream) 162 { 163 struct snd_dg00x *dg00x = substream->private_data; 164 165 snd_dg00x_stream_lock_release(dg00x); 166 167 return 0; 168 } 169 170 static int pcm_capture_hw_params(struct snd_pcm_substream *substream, 171 struct snd_pcm_hw_params *hw_params) 172 { 173 struct snd_dg00x *dg00x = substream->private_data; 174 int err; 175 176 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 177 params_buffer_bytes(hw_params)); 178 if (err < 0) 179 return err; 180 181 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 182 mutex_lock(&dg00x->mutex); 183 dg00x->substreams_counter++; 184 mutex_unlock(&dg00x->mutex); 185 } 186 187 amdtp_dot_set_pcm_format(&dg00x->tx_stream, params_format(hw_params)); 188 189 return 0; 190 } 191 192 static int pcm_playback_hw_params(struct snd_pcm_substream *substream, 193 struct snd_pcm_hw_params *hw_params) 194 { 195 struct snd_dg00x *dg00x = substream->private_data; 196 int err; 197 198 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 199 params_buffer_bytes(hw_params)); 200 if (err < 0) 201 return err; 202 203 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 204 mutex_lock(&dg00x->mutex); 205 dg00x->substreams_counter++; 206 mutex_unlock(&dg00x->mutex); 207 } 208 209 amdtp_dot_set_pcm_format(&dg00x->rx_stream, params_format(hw_params)); 210 211 return 0; 212 } 213 214 static int pcm_capture_hw_free(struct snd_pcm_substream *substream) 215 { 216 struct snd_dg00x *dg00x = substream->private_data; 217 218 mutex_lock(&dg00x->mutex); 219 220 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 221 dg00x->substreams_counter--; 222 223 snd_dg00x_stream_stop_duplex(dg00x); 224 225 mutex_unlock(&dg00x->mutex); 226 227 return snd_pcm_lib_free_vmalloc_buffer(substream); 228 } 229 230 static int pcm_playback_hw_free(struct snd_pcm_substream *substream) 231 { 232 struct snd_dg00x *dg00x = substream->private_data; 233 234 mutex_lock(&dg00x->mutex); 235 236 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 237 dg00x->substreams_counter--; 238 239 snd_dg00x_stream_stop_duplex(dg00x); 240 241 mutex_unlock(&dg00x->mutex); 242 243 return snd_pcm_lib_free_vmalloc_buffer(substream); 244 } 245 246 static int pcm_capture_prepare(struct snd_pcm_substream *substream) 247 { 248 struct snd_dg00x *dg00x = substream->private_data; 249 struct snd_pcm_runtime *runtime = substream->runtime; 250 int err; 251 252 mutex_lock(&dg00x->mutex); 253 254 err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate); 255 if (err >= 0) 256 amdtp_stream_pcm_prepare(&dg00x->tx_stream); 257 258 mutex_unlock(&dg00x->mutex); 259 260 return err; 261 } 262 263 static int pcm_playback_prepare(struct snd_pcm_substream *substream) 264 { 265 struct snd_dg00x *dg00x = substream->private_data; 266 struct snd_pcm_runtime *runtime = substream->runtime; 267 int err; 268 269 mutex_lock(&dg00x->mutex); 270 271 err = snd_dg00x_stream_start_duplex(dg00x, runtime->rate); 272 if (err >= 0) { 273 amdtp_stream_pcm_prepare(&dg00x->rx_stream); 274 amdtp_dot_reset(&dg00x->rx_stream); 275 } 276 277 mutex_unlock(&dg00x->mutex); 278 279 return err; 280 } 281 282 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 283 { 284 struct snd_dg00x *dg00x = substream->private_data; 285 286 switch (cmd) { 287 case SNDRV_PCM_TRIGGER_START: 288 amdtp_stream_pcm_trigger(&dg00x->tx_stream, substream); 289 break; 290 case SNDRV_PCM_TRIGGER_STOP: 291 amdtp_stream_pcm_trigger(&dg00x->tx_stream, NULL); 292 break; 293 default: 294 return -EINVAL; 295 } 296 297 return 0; 298 } 299 300 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 301 { 302 struct snd_dg00x *dg00x = substream->private_data; 303 304 switch (cmd) { 305 case SNDRV_PCM_TRIGGER_START: 306 amdtp_stream_pcm_trigger(&dg00x->rx_stream, substream); 307 break; 308 case SNDRV_PCM_TRIGGER_STOP: 309 amdtp_stream_pcm_trigger(&dg00x->rx_stream, NULL); 310 break; 311 default: 312 return -EINVAL; 313 } 314 315 return 0; 316 } 317 318 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) 319 { 320 struct snd_dg00x *dg00x = sbstrm->private_data; 321 322 return amdtp_stream_pcm_pointer(&dg00x->tx_stream); 323 } 324 325 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) 326 { 327 struct snd_dg00x *dg00x = sbstrm->private_data; 328 329 return amdtp_stream_pcm_pointer(&dg00x->rx_stream); 330 } 331 332 int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) 333 { 334 static const struct snd_pcm_ops capture_ops = { 335 .open = pcm_open, 336 .close = pcm_close, 337 .ioctl = snd_pcm_lib_ioctl, 338 .hw_params = pcm_capture_hw_params, 339 .hw_free = pcm_capture_hw_free, 340 .prepare = pcm_capture_prepare, 341 .trigger = pcm_capture_trigger, 342 .pointer = pcm_capture_pointer, 343 .page = snd_pcm_lib_get_vmalloc_page, 344 }; 345 static const struct snd_pcm_ops playback_ops = { 346 .open = pcm_open, 347 .close = pcm_close, 348 .ioctl = snd_pcm_lib_ioctl, 349 .hw_params = pcm_playback_hw_params, 350 .hw_free = pcm_playback_hw_free, 351 .prepare = pcm_playback_prepare, 352 .trigger = pcm_playback_trigger, 353 .pointer = pcm_playback_pointer, 354 .page = snd_pcm_lib_get_vmalloc_page, 355 .mmap = snd_pcm_lib_mmap_vmalloc, 356 }; 357 struct snd_pcm *pcm; 358 int err; 359 360 err = snd_pcm_new(dg00x->card, dg00x->card->driver, 0, 1, 1, &pcm); 361 if (err < 0) 362 return err; 363 364 pcm->private_data = dg00x; 365 snprintf(pcm->name, sizeof(pcm->name), 366 "%s PCM", dg00x->card->shortname); 367 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 368 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops); 369 370 return 0; 371 } 372