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 int init_hw_params(struct snd_oxfw *oxfw, 110 struct snd_pcm_substream *substream) 111 { 112 struct snd_pcm_runtime *runtime = substream->runtime; 113 u8 **formats; 114 struct amdtp_stream *stream; 115 int err; 116 117 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 118 runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; 119 stream = &oxfw->tx_stream; 120 formats = oxfw->tx_stream_formats; 121 } else { 122 runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS; 123 stream = &oxfw->rx_stream; 124 formats = oxfw->rx_stream_formats; 125 } 126 127 limit_channels_and_rates(&runtime->hw, formats); 128 129 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 130 hw_rule_channels, formats, 131 SNDRV_PCM_HW_PARAM_RATE, -1); 132 if (err < 0) 133 goto end; 134 135 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 136 hw_rule_rate, formats, 137 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 138 if (err < 0) 139 goto end; 140 141 err = amdtp_am824_add_pcm_hw_constraints(stream, runtime); 142 end: 143 return err; 144 } 145 146 static int limit_to_current_params(struct snd_pcm_substream *substream) 147 { 148 struct snd_oxfw *oxfw = substream->private_data; 149 struct snd_oxfw_stream_formation formation; 150 enum avc_general_plug_dir dir; 151 int err; 152 153 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 154 dir = AVC_GENERAL_PLUG_DIR_OUT; 155 else 156 dir = AVC_GENERAL_PLUG_DIR_IN; 157 158 err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); 159 if (err < 0) 160 goto end; 161 162 substream->runtime->hw.channels_min = formation.pcm; 163 substream->runtime->hw.channels_max = formation.pcm; 164 substream->runtime->hw.rate_min = formation.rate; 165 substream->runtime->hw.rate_max = formation.rate; 166 end: 167 return err; 168 } 169 170 static int pcm_open(struct snd_pcm_substream *substream) 171 { 172 struct snd_oxfw *oxfw = substream->private_data; 173 int err; 174 175 err = snd_oxfw_stream_lock_try(oxfw); 176 if (err < 0) 177 goto end; 178 179 err = init_hw_params(oxfw, substream); 180 if (err < 0) 181 goto err_locked; 182 183 /* 184 * When any PCM streams are already running, the available sampling 185 * rate is limited at current value. 186 */ 187 if (amdtp_stream_pcm_running(&oxfw->tx_stream) || 188 amdtp_stream_pcm_running(&oxfw->rx_stream)) { 189 err = limit_to_current_params(substream); 190 if (err < 0) 191 goto end; 192 } 193 194 snd_pcm_set_sync(substream); 195 end: 196 return err; 197 err_locked: 198 snd_oxfw_stream_lock_release(oxfw); 199 return err; 200 } 201 202 static int pcm_close(struct snd_pcm_substream *substream) 203 { 204 struct snd_oxfw *oxfw = substream->private_data; 205 206 snd_oxfw_stream_lock_release(oxfw); 207 return 0; 208 } 209 210 static int pcm_capture_hw_params(struct snd_pcm_substream *substream, 211 struct snd_pcm_hw_params *hw_params) 212 { 213 struct snd_oxfw *oxfw = substream->private_data; 214 int err; 215 216 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 217 params_buffer_bytes(hw_params)); 218 if (err < 0) 219 return err; 220 221 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 222 mutex_lock(&oxfw->mutex); 223 oxfw->capture_substreams++; 224 mutex_unlock(&oxfw->mutex); 225 } 226 227 return 0; 228 } 229 static int pcm_playback_hw_params(struct snd_pcm_substream *substream, 230 struct snd_pcm_hw_params *hw_params) 231 { 232 struct snd_oxfw *oxfw = substream->private_data; 233 int err; 234 235 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 236 params_buffer_bytes(hw_params)); 237 if (err < 0) 238 return err; 239 240 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { 241 mutex_lock(&oxfw->mutex); 242 oxfw->playback_substreams++; 243 mutex_unlock(&oxfw->mutex); 244 } 245 246 return 0; 247 } 248 249 static int pcm_capture_hw_free(struct snd_pcm_substream *substream) 250 { 251 struct snd_oxfw *oxfw = substream->private_data; 252 253 mutex_lock(&oxfw->mutex); 254 255 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 256 oxfw->capture_substreams--; 257 258 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream); 259 260 mutex_unlock(&oxfw->mutex); 261 262 return snd_pcm_lib_free_vmalloc_buffer(substream); 263 } 264 static int pcm_playback_hw_free(struct snd_pcm_substream *substream) 265 { 266 struct snd_oxfw *oxfw = substream->private_data; 267 268 mutex_lock(&oxfw->mutex); 269 270 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 271 oxfw->playback_substreams--; 272 273 snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream); 274 275 mutex_unlock(&oxfw->mutex); 276 277 return snd_pcm_lib_free_vmalloc_buffer(substream); 278 } 279 280 static int pcm_capture_prepare(struct snd_pcm_substream *substream) 281 { 282 struct snd_oxfw *oxfw = substream->private_data; 283 struct snd_pcm_runtime *runtime = substream->runtime; 284 int err; 285 286 mutex_lock(&oxfw->mutex); 287 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 288 runtime->rate, runtime->channels); 289 mutex_unlock(&oxfw->mutex); 290 if (err < 0) 291 goto end; 292 293 amdtp_stream_pcm_prepare(&oxfw->tx_stream); 294 end: 295 return err; 296 } 297 static int pcm_playback_prepare(struct snd_pcm_substream *substream) 298 { 299 struct snd_oxfw *oxfw = substream->private_data; 300 struct snd_pcm_runtime *runtime = substream->runtime; 301 int err; 302 303 mutex_lock(&oxfw->mutex); 304 err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 305 runtime->rate, runtime->channels); 306 mutex_unlock(&oxfw->mutex); 307 if (err < 0) 308 goto end; 309 310 amdtp_stream_pcm_prepare(&oxfw->rx_stream); 311 end: 312 return err; 313 } 314 315 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 316 { 317 struct snd_oxfw *oxfw = substream->private_data; 318 struct snd_pcm_substream *pcm; 319 320 switch (cmd) { 321 case SNDRV_PCM_TRIGGER_START: 322 pcm = substream; 323 break; 324 case SNDRV_PCM_TRIGGER_STOP: 325 pcm = NULL; 326 break; 327 default: 328 return -EINVAL; 329 } 330 amdtp_stream_pcm_trigger(&oxfw->tx_stream, pcm); 331 return 0; 332 } 333 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 334 { 335 struct snd_oxfw *oxfw = substream->private_data; 336 struct snd_pcm_substream *pcm; 337 338 switch (cmd) { 339 case SNDRV_PCM_TRIGGER_START: 340 pcm = substream; 341 break; 342 case SNDRV_PCM_TRIGGER_STOP: 343 pcm = NULL; 344 break; 345 default: 346 return -EINVAL; 347 } 348 amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm); 349 return 0; 350 } 351 352 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstm) 353 { 354 struct snd_oxfw *oxfw = sbstm->private_data; 355 356 return amdtp_stream_pcm_pointer(&oxfw->tx_stream); 357 } 358 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) 359 { 360 struct snd_oxfw *oxfw = sbstm->private_data; 361 362 return amdtp_stream_pcm_pointer(&oxfw->rx_stream); 363 } 364 365 static int pcm_capture_ack(struct snd_pcm_substream *substream) 366 { 367 struct snd_oxfw *oxfw = substream->private_data; 368 369 return amdtp_stream_pcm_ack(&oxfw->tx_stream); 370 } 371 372 static int pcm_playback_ack(struct snd_pcm_substream *substream) 373 { 374 struct snd_oxfw *oxfw = substream->private_data; 375 376 return amdtp_stream_pcm_ack(&oxfw->rx_stream); 377 } 378 379 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) 380 { 381 static const struct snd_pcm_ops capture_ops = { 382 .open = pcm_open, 383 .close = pcm_close, 384 .ioctl = snd_pcm_lib_ioctl, 385 .hw_params = pcm_capture_hw_params, 386 .hw_free = pcm_capture_hw_free, 387 .prepare = pcm_capture_prepare, 388 .trigger = pcm_capture_trigger, 389 .pointer = pcm_capture_pointer, 390 .ack = pcm_capture_ack, 391 .page = snd_pcm_lib_get_vmalloc_page, 392 }; 393 static const struct snd_pcm_ops playback_ops = { 394 .open = pcm_open, 395 .close = pcm_close, 396 .ioctl = snd_pcm_lib_ioctl, 397 .hw_params = pcm_playback_hw_params, 398 .hw_free = pcm_playback_hw_free, 399 .prepare = pcm_playback_prepare, 400 .trigger = pcm_playback_trigger, 401 .pointer = pcm_playback_pointer, 402 .ack = pcm_playback_ack, 403 .page = snd_pcm_lib_get_vmalloc_page, 404 }; 405 struct snd_pcm *pcm; 406 unsigned int cap = 0; 407 int err; 408 409 if (oxfw->has_output) 410 cap = 1; 411 412 err = snd_pcm_new(oxfw->card, oxfw->card->driver, 0, 1, cap, &pcm); 413 if (err < 0) 414 return err; 415 416 pcm->private_data = oxfw; 417 strcpy(pcm->name, oxfw->card->shortname); 418 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops); 419 if (cap > 0) 420 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops); 421 422 return 0; 423 } 424