1 /* 2 * oxfw_pcm.c - a part of driver for OXFW970/971 based devices 3 * 4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 5 * Licensed under the terms of the GNU General Public License, version 2. 6 */ 7 8 #include "oxfw.h" 9 10 static int hw_rule_rate(struct snd_pcm_hw_params *params, 11 struct snd_pcm_hw_rule *rule) 12 { 13 u8 **formats = 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 struct snd_oxfw_stream_formation formation; 22 int i, err; 23 24 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { 25 if (formats[i] == NULL) 26 continue; 27 28 err = snd_oxfw_stream_parse_format(formats[i], &formation); 29 if (err < 0) 30 continue; 31 if (!snd_interval_test(c, formation.pcm)) 32 continue; 33 34 t.min = min(t.min, formation.rate); 35 t.max = max(t.max, formation.rate); 36 37 } 38 return snd_interval_refine(r, &t); 39 } 40 41 static int hw_rule_channels(struct snd_pcm_hw_params *params, 42 struct snd_pcm_hw_rule *rule) 43 { 44 u8 **formats = 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_oxfw_stream_formation formation; 50 int i, j, err; 51 unsigned int count, list[SND_OXFW_STREAM_FORMAT_ENTRIES] = {0}; 52 53 count = 0; 54 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { 55 if (formats[i] == NULL) 56 break; 57 58 err = snd_oxfw_stream_parse_format(formats[i], &formation); 59 if (err < 0) 60 continue; 61 if (!snd_interval_test(r, formation.rate)) 62 continue; 63 if (list[count] == formation.pcm) 64 continue; 65 66 for (j = 0; j < ARRAY_SIZE(list); j++) { 67 if (list[j] == formation.pcm) 68 break; 69 } 70 if (j == ARRAY_SIZE(list)) { 71 list[count] = formation.pcm; 72 if (++count == ARRAY_SIZE(list)) 73 break; 74 } 75 } 76 77 return snd_interval_list(c, count, list, 0); 78 } 79 80 static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats) 81 { 82 struct snd_oxfw_stream_formation formation; 83 int i, err; 84 85 hw->channels_min = UINT_MAX; 86 hw->channels_max = 0; 87 88 hw->rate_min = UINT_MAX; 89 hw->rate_max = 0; 90 hw->rates = 0; 91 92 for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { 93 if (formats[i] == NULL) 94 break; 95 96 err = snd_oxfw_stream_parse_format(formats[i], &formation); 97 if (err < 0) 98 continue; 99 100 hw->channels_min = min(hw->channels_min, formation.pcm); 101 hw->channels_max = max(hw->channels_max, formation.pcm); 102 103 hw->rate_min = min(hw->rate_min, formation.rate); 104 hw->rate_max = max(hw->rate_max, formation.rate); 105 hw->rates |= snd_pcm_rate_to_rate_bit(formation.rate); 106 } 107 } 108 109 static void limit_period_and_buffer(struct snd_pcm_hardware *hw) 110 { 111 hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ 112 hw->periods_max = UINT_MAX; 113 114 hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ 115 116 /* Just to prevent from allocating much pages. */ 117 hw->period_bytes_max = hw->period_bytes_min * 2048; 118 hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; 119 } 120 121 static int init_hw_params(struct snd_oxfw *oxfw, 122 struct snd_pcm_substream *substream) 123 { 124 struct snd_pcm_runtime *runtime = substream->runtime; 125 u8 **formats; 126 struct amdtp_stream *stream; 127 int err; 128 129 runtime->hw.info = SNDRV_PCM_INFO_BATCH | 130 SNDRV_PCM_INFO_BLOCK_TRANSFER | 131 SNDRV_PCM_INFO_INTERLEAVED | 132 SNDRV_PCM_INFO_JOINT_DUPLEX | 133 SNDRV_PCM_INFO_MMAP | 134 SNDRV_PCM_INFO_MMAP_VALID; 135 136 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 137 runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; 138 stream = &oxfw->tx_stream; 139 formats = oxfw->tx_stream_formats; 140 } else { 141 runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS; 142 stream = &oxfw->rx_stream; 143 formats = oxfw->rx_stream_formats; 144 } 145 146 limit_channels_and_rates(&runtime->hw, formats); 147 limit_period_and_buffer(&runtime->hw); 148 149 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 150 hw_rule_channels, formats, 151 SNDRV_PCM_HW_PARAM_RATE, -1); 152 if (err < 0) 153 goto end; 154 155 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 156 hw_rule_rate, formats, 157 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 158 if (err < 0) 159 goto end; 160 161 err = amdtp_am824_add_pcm_hw_constraints(stream, runtime); 162 end: 163 return err; 164 } 165 166 static int limit_to_current_params(struct snd_pcm_substream *substream) 167 { 168 struct snd_oxfw *oxfw = substream->private_data; 169 struct snd_oxfw_stream_formation formation; 170 enum avc_general_plug_dir dir; 171 int err; 172 173 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 174 dir = AVC_GENERAL_PLUG_DIR_OUT; 175 else 176 dir = AVC_GENERAL_PLUG_DIR_IN; 177 178 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); 179 if (err < 0) 180 goto end; 181 182 substream->runtime->hw.channels_min = formation.pcm; 183 substream->runtime->hw.channels_max = formation.pcm; 184 substream->runtime->hw.rate_min = formation.rate; 185 substream->runtime->hw.rate_max = formation.rate; 186 end: 187 return err; 188 } 189 190 static int pcm_open(struct snd_pcm_substream *substream) 191 { 192 struct snd_oxfw *oxfw = substream->private_data; 193 int err; 194 195 err = snd_oxfw_stream_lock_try(oxfw); 196 if (err < 0) 197 goto end; 198 199 err = init_hw_params(oxfw, substream); 200 if (err < 0) 201 goto err_locked; 202 203 /* 204 * When any PCM streams are already running, the available sampling 205 * rate is limited at current value. 206 */ 207 if (amdtp_stream_pcm_running(&oxfw->tx_stream) || 208 amdtp_stream_pcm_running(&oxfw->rx_stream)) { 209 err = limit_to_current_params(substream); 210 if (err < 0) 211 goto end; 212 } 213 214 snd_pcm_set_sync(substream); 215 end: 216 return err; 217 err_locked: 218 snd_oxfw_stream_lock_release(oxfw); 219 return err; 220 } 221 222 static int pcm_close(struct snd_pcm_substream *substream) 223 { 224 struct snd_oxfw *oxfw = substream->private_data; 225 226 snd_oxfw_stream_lock_release(oxfw); 227 return 0; 228 } 229 230 static int pcm_capture_hw_params(struct snd_pcm_substream *substream, 231 struct snd_pcm_hw_params *hw_params) 232 { 233 struct snd_oxfw *oxfw = substream->private_data; 234 int err; 235 236 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 237 params_buffer_bytes(hw_params)); 238 if (err < 0) 239 return err; 240 241 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 242 mutex_lock(&oxfw->mutex); 243 oxfw->capture_substreams++; 244 mutex_unlock(&oxfw->mutex); 245 } 246 247 amdtp_am824_set_pcm_format(&oxfw->tx_stream, params_format(hw_params)); 248 249 return 0; 250 } 251 static int pcm_playback_hw_params(struct snd_pcm_substream *substream, 252 struct snd_pcm_hw_params *hw_params) 253 { 254 struct snd_oxfw *oxfw = substream->private_data; 255 int err; 256 257 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 258 params_buffer_bytes(hw_params)); 259 if (err < 0) 260 return err; 261 262 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 263 mutex_lock(&oxfw->mutex); 264 oxfw->playback_substreams++; 265 mutex_unlock(&oxfw->mutex); 266 } 267 268 amdtp_am824_set_pcm_format(&oxfw->rx_stream, params_format(hw_params)); 269 270 return 0; 271 } 272 273 static int pcm_capture_hw_free(struct snd_pcm_substream *substream) 274 { 275 struct snd_oxfw *oxfw = substream->private_data; 276 277 mutex_lock(&oxfw->mutex); 278 279 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 280 oxfw->capture_substreams--; 281 282 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream); 283 284 mutex_unlock(&oxfw->mutex); 285 286 return snd_pcm_lib_free_vmalloc_buffer(substream); 287 } 288 static int pcm_playback_hw_free(struct snd_pcm_substream *substream) 289 { 290 struct snd_oxfw *oxfw = substream->private_data; 291 292 mutex_lock(&oxfw->mutex); 293 294 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 295 oxfw->playback_substreams--; 296 297 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream); 298 299 mutex_unlock(&oxfw->mutex); 300 301 return snd_pcm_lib_free_vmalloc_buffer(substream); 302 } 303 304 static int pcm_capture_prepare(struct snd_pcm_substream *substream) 305 { 306 struct snd_oxfw *oxfw = substream->private_data; 307 struct snd_pcm_runtime *runtime = substream->runtime; 308 int err; 309 310 mutex_lock(&oxfw->mutex); 311 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 312 runtime->rate, runtime->channels); 313 mutex_unlock(&oxfw->mutex); 314 if (err < 0) 315 goto end; 316 317 amdtp_stream_pcm_prepare(&oxfw->tx_stream); 318 end: 319 return err; 320 } 321 static int pcm_playback_prepare(struct snd_pcm_substream *substream) 322 { 323 struct snd_oxfw *oxfw = substream->private_data; 324 struct snd_pcm_runtime *runtime = substream->runtime; 325 int err; 326 327 mutex_lock(&oxfw->mutex); 328 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 329 runtime->rate, runtime->channels); 330 mutex_unlock(&oxfw->mutex); 331 if (err < 0) 332 goto end; 333 334 amdtp_stream_pcm_prepare(&oxfw->rx_stream); 335 end: 336 return err; 337 } 338 339 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 340 { 341 struct snd_oxfw *oxfw = substream->private_data; 342 struct snd_pcm_substream *pcm; 343 344 switch (cmd) { 345 case SNDRV_PCM_TRIGGER_START: 346 pcm = substream; 347 break; 348 case SNDRV_PCM_TRIGGER_STOP: 349 pcm = NULL; 350 break; 351 default: 352 return -EINVAL; 353 } 354 amdtp_stream_pcm_trigger(&oxfw->tx_stream, pcm); 355 return 0; 356 } 357 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 358 { 359 struct snd_oxfw *oxfw = substream->private_data; 360 struct snd_pcm_substream *pcm; 361 362 switch (cmd) { 363 case SNDRV_PCM_TRIGGER_START: 364 pcm = substream; 365 break; 366 case SNDRV_PCM_TRIGGER_STOP: 367 pcm = NULL; 368 break; 369 default: 370 return -EINVAL; 371 } 372 amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm); 373 return 0; 374 } 375 376 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstm) 377 { 378 struct snd_oxfw *oxfw = sbstm->private_data; 379 380 return amdtp_stream_pcm_pointer(&oxfw->tx_stream); 381 } 382 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) 383 { 384 struct snd_oxfw *oxfw = sbstm->private_data; 385 386 return amdtp_stream_pcm_pointer(&oxfw->rx_stream); 387 } 388 389 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) 390 { 391 static struct snd_pcm_ops capture_ops = { 392 .open = pcm_open, 393 .close = pcm_close, 394 .ioctl = snd_pcm_lib_ioctl, 395 .hw_params = pcm_capture_hw_params, 396 .hw_free = pcm_capture_hw_free, 397 .prepare = pcm_capture_prepare, 398 .trigger = pcm_capture_trigger, 399 .pointer = pcm_capture_pointer, 400 .page = snd_pcm_lib_get_vmalloc_page, 401 .mmap = snd_pcm_lib_mmap_vmalloc, 402 }; 403 static struct snd_pcm_ops playback_ops = { 404 .open = pcm_open, 405 .close = pcm_close, 406 .ioctl = snd_pcm_lib_ioctl, 407 .hw_params = pcm_playback_hw_params, 408 .hw_free = pcm_playback_hw_free, 409 .prepare = pcm_playback_prepare, 410 .trigger = pcm_playback_trigger, 411 .pointer = pcm_playback_pointer, 412 .page = snd_pcm_lib_get_vmalloc_page, 413 .mmap = snd_pcm_lib_mmap_vmalloc, 414 }; 415 struct snd_pcm *pcm; 416 unsigned int cap = 0; 417 int err; 418 419 if (oxfw->has_output) 420 cap = 1; 421 422 err = snd_pcm_new(oxfw->card, oxfw->card->driver, 0, 1, cap, &pcm); 423 if (err < 0) 424 return err; 425 426 pcm->private_data = oxfw; 427 strcpy(pcm->name, oxfw->card->shortname); 428 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 429 if (cap > 0) 430 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops); 431 432 return 0; 433 } 434