ff-pcm.c (9820B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * ff-pcm.c - a part of driver for RME Fireface series 4 * 5 * Copyright (c) 2015-2017 Takashi Sakamoto 6 */ 7 8#include "ff.h" 9 10static int hw_rule_rate(struct snd_pcm_hw_params *params, 11 struct snd_pcm_hw_rule *rule) 12{ 13 const unsigned int *pcm_channels = rule->private; 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 < ARRAY_SIZE(amdtp_rate_table); i++) { 24 enum snd_ff_stream_mode mode; 25 int err; 26 27 err = snd_ff_stream_get_multiplier_mode(i, &mode); 28 if (err < 0) 29 continue; 30 31 if (!snd_interval_test(c, pcm_channels[mode])) 32 continue; 33 34 t.min = min(t.min, amdtp_rate_table[i]); 35 t.max = max(t.max, amdtp_rate_table[i]); 36 } 37 38 return snd_interval_refine(r, &t); 39} 40 41static int hw_rule_channels(struct snd_pcm_hw_params *params, 42 struct snd_pcm_hw_rule *rule) 43{ 44 const unsigned int *pcm_channels = rule->private; 45 struct snd_interval *c = 46 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 47 const struct snd_interval *r = 48 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); 49 struct snd_interval t = { 50 .min = UINT_MAX, .max = 0, .integer = 1 51 }; 52 unsigned int i; 53 54 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) { 55 enum snd_ff_stream_mode mode; 56 int err; 57 58 err = snd_ff_stream_get_multiplier_mode(i, &mode); 59 if (err < 0) 60 continue; 61 62 if (!snd_interval_test(r, amdtp_rate_table[i])) 63 continue; 64 65 t.min = min(t.min, pcm_channels[mode]); 66 t.max = max(t.max, pcm_channels[mode]); 67 } 68 69 return snd_interval_refine(c, &t); 70} 71 72static void limit_channels_and_rates(struct snd_pcm_hardware *hw, 73 const unsigned int *pcm_channels) 74{ 75 unsigned int rate, channels; 76 int i; 77 78 hw->channels_min = UINT_MAX; 79 hw->channels_max = 0; 80 hw->rate_min = UINT_MAX; 81 hw->rate_max = 0; 82 83 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) { 84 enum snd_ff_stream_mode mode; 85 int err; 86 87 err = snd_ff_stream_get_multiplier_mode(i, &mode); 88 if (err < 0) 89 continue; 90 91 channels = pcm_channels[mode]; 92 if (pcm_channels[mode] == 0) 93 continue; 94 hw->channels_min = min(hw->channels_min, channels); 95 hw->channels_max = max(hw->channels_max, channels); 96 97 rate = amdtp_rate_table[i]; 98 hw->rates |= snd_pcm_rate_to_rate_bit(rate); 99 hw->rate_min = min(hw->rate_min, rate); 100 hw->rate_max = max(hw->rate_max, rate); 101 } 102} 103 104static int pcm_init_hw_params(struct snd_ff *ff, 105 struct snd_pcm_substream *substream) 106{ 107 struct snd_pcm_runtime *runtime = substream->runtime; 108 struct amdtp_stream *s; 109 const unsigned int *pcm_channels; 110 int err; 111 112 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 113 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; 114 s = &ff->tx_stream; 115 pcm_channels = ff->spec->pcm_capture_channels; 116 } else { 117 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; 118 s = &ff->rx_stream; 119 pcm_channels = ff->spec->pcm_playback_channels; 120 } 121 122 limit_channels_and_rates(&runtime->hw, pcm_channels); 123 124 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 125 hw_rule_channels, (void *)pcm_channels, 126 SNDRV_PCM_HW_PARAM_RATE, -1); 127 if (err < 0) 128 return err; 129 130 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 131 hw_rule_rate, (void *)pcm_channels, 132 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 133 if (err < 0) 134 return err; 135 136 return amdtp_ff_add_pcm_hw_constraints(s, runtime); 137} 138 139static int pcm_open(struct snd_pcm_substream *substream) 140{ 141 struct snd_ff *ff = substream->private_data; 142 struct amdtp_domain *d = &ff->domain; 143 unsigned int rate; 144 enum snd_ff_clock_src src; 145 int i, err; 146 147 err = snd_ff_stream_lock_try(ff); 148 if (err < 0) 149 return err; 150 151 err = pcm_init_hw_params(ff, substream); 152 if (err < 0) 153 goto release_lock; 154 155 err = ff->spec->protocol->get_clock(ff, &rate, &src); 156 if (err < 0) 157 goto release_lock; 158 159 mutex_lock(&ff->mutex); 160 161 // When source of clock is not internal or any stream is reserved for 162 // transmission of PCM frames, the available sampling rate is limited 163 // at current one. 164 if (src != SND_FF_CLOCK_SRC_INTERNAL) { 165 for (i = 0; i < CIP_SFC_COUNT; ++i) { 166 if (amdtp_rate_table[i] == rate) 167 break; 168 } 169 170 // The unit is configured at sampling frequency which packet 171 // streaming engine can't support. 172 if (i >= CIP_SFC_COUNT) { 173 mutex_unlock(&ff->mutex); 174 err = -EIO; 175 goto release_lock; 176 } 177 178 substream->runtime->hw.rate_min = rate; 179 substream->runtime->hw.rate_max = rate; 180 } else { 181 if (ff->substreams_counter > 0) { 182 unsigned int frames_per_period = d->events_per_period; 183 unsigned int frames_per_buffer = d->events_per_buffer; 184 185 rate = amdtp_rate_table[ff->rx_stream.sfc]; 186 substream->runtime->hw.rate_min = rate; 187 substream->runtime->hw.rate_max = rate; 188 189 err = snd_pcm_hw_constraint_minmax(substream->runtime, 190 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 191 frames_per_period, frames_per_period); 192 if (err < 0) { 193 mutex_unlock(&ff->mutex); 194 goto release_lock; 195 } 196 197 err = snd_pcm_hw_constraint_minmax(substream->runtime, 198 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 199 frames_per_buffer, frames_per_buffer); 200 if (err < 0) { 201 mutex_unlock(&ff->mutex); 202 goto release_lock; 203 } 204 } 205 } 206 207 mutex_unlock(&ff->mutex); 208 209 snd_pcm_set_sync(substream); 210 211 return 0; 212 213release_lock: 214 snd_ff_stream_lock_release(ff); 215 return err; 216} 217 218static int pcm_close(struct snd_pcm_substream *substream) 219{ 220 struct snd_ff *ff = substream->private_data; 221 222 snd_ff_stream_lock_release(ff); 223 224 return 0; 225} 226 227static int pcm_hw_params(struct snd_pcm_substream *substream, 228 struct snd_pcm_hw_params *hw_params) 229{ 230 struct snd_ff *ff = substream->private_data; 231 int err = 0; 232 233 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 234 unsigned int rate = params_rate(hw_params); 235 unsigned int frames_per_period = params_period_size(hw_params); 236 unsigned int frames_per_buffer = params_buffer_size(hw_params); 237 238 mutex_lock(&ff->mutex); 239 err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period, 240 frames_per_buffer); 241 if (err >= 0) 242 ++ff->substreams_counter; 243 mutex_unlock(&ff->mutex); 244 } 245 246 return err; 247} 248 249static int pcm_hw_free(struct snd_pcm_substream *substream) 250{ 251 struct snd_ff *ff = substream->private_data; 252 253 mutex_lock(&ff->mutex); 254 255 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 256 --ff->substreams_counter; 257 258 snd_ff_stream_stop_duplex(ff); 259 260 mutex_unlock(&ff->mutex); 261 262 return 0; 263} 264 265static int pcm_capture_prepare(struct snd_pcm_substream *substream) 266{ 267 struct snd_ff *ff = substream->private_data; 268 struct snd_pcm_runtime *runtime = substream->runtime; 269 int err; 270 271 mutex_lock(&ff->mutex); 272 273 err = snd_ff_stream_start_duplex(ff, runtime->rate); 274 if (err >= 0) 275 amdtp_stream_pcm_prepare(&ff->tx_stream); 276 277 mutex_unlock(&ff->mutex); 278 279 return err; 280} 281 282static int pcm_playback_prepare(struct snd_pcm_substream *substream) 283{ 284 struct snd_ff *ff = substream->private_data; 285 struct snd_pcm_runtime *runtime = substream->runtime; 286 int err; 287 288 mutex_lock(&ff->mutex); 289 290 err = snd_ff_stream_start_duplex(ff, runtime->rate); 291 if (err >= 0) 292 amdtp_stream_pcm_prepare(&ff->rx_stream); 293 294 mutex_unlock(&ff->mutex); 295 296 return err; 297} 298 299static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 300{ 301 struct snd_ff *ff = substream->private_data; 302 303 switch (cmd) { 304 case SNDRV_PCM_TRIGGER_START: 305 amdtp_stream_pcm_trigger(&ff->tx_stream, substream); 306 break; 307 case SNDRV_PCM_TRIGGER_STOP: 308 amdtp_stream_pcm_trigger(&ff->tx_stream, NULL); 309 break; 310 default: 311 return -EINVAL; 312 } 313 314 return 0; 315} 316 317static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 318{ 319 struct snd_ff *ff = substream->private_data; 320 321 switch (cmd) { 322 case SNDRV_PCM_TRIGGER_START: 323 amdtp_stream_pcm_trigger(&ff->rx_stream, substream); 324 break; 325 case SNDRV_PCM_TRIGGER_STOP: 326 amdtp_stream_pcm_trigger(&ff->rx_stream, NULL); 327 break; 328 default: 329 return -EINVAL; 330 } 331 332 return 0; 333} 334 335static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) 336{ 337 struct snd_ff *ff = sbstrm->private_data; 338 339 return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->tx_stream); 340} 341 342static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) 343{ 344 struct snd_ff *ff = sbstrm->private_data; 345 346 return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->rx_stream); 347} 348 349static int pcm_capture_ack(struct snd_pcm_substream *substream) 350{ 351 struct snd_ff *ff = substream->private_data; 352 353 return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->tx_stream); 354} 355 356static int pcm_playback_ack(struct snd_pcm_substream *substream) 357{ 358 struct snd_ff *ff = substream->private_data; 359 360 return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->rx_stream); 361} 362 363int snd_ff_create_pcm_devices(struct snd_ff *ff) 364{ 365 static const struct snd_pcm_ops pcm_capture_ops = { 366 .open = pcm_open, 367 .close = pcm_close, 368 .hw_params = pcm_hw_params, 369 .hw_free = pcm_hw_free, 370 .prepare = pcm_capture_prepare, 371 .trigger = pcm_capture_trigger, 372 .pointer = pcm_capture_pointer, 373 .ack = pcm_capture_ack, 374 }; 375 static const struct snd_pcm_ops pcm_playback_ops = { 376 .open = pcm_open, 377 .close = pcm_close, 378 .hw_params = pcm_hw_params, 379 .hw_free = pcm_hw_free, 380 .prepare = pcm_playback_prepare, 381 .trigger = pcm_playback_trigger, 382 .pointer = pcm_playback_pointer, 383 .ack = pcm_playback_ack, 384 }; 385 struct snd_pcm *pcm; 386 int err; 387 388 err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm); 389 if (err < 0) 390 return err; 391 392 pcm->private_data = ff; 393 snprintf(pcm->name, sizeof(pcm->name), 394 "%s PCM", ff->card->shortname); 395 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops); 396 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); 397 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); 398 399 return 0; 400}