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