aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c1013
1 files changed, 559 insertions, 454 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index faa2e2be6f2e..b3d5bed75029 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -37,6 +37,18 @@
37#include <sound/minors.h> 37#include <sound/minors.h>
38#include <linux/uio.h> 38#include <linux/uio.h>
39 39
40#include "pcm_local.h"
41
42#ifdef CONFIG_SND_DEBUG
43#define CREATE_TRACE_POINTS
44#include "pcm_param_trace.h"
45#else
46#define trace_hw_mask_param_enabled() 0
47#define trace_hw_interval_param_enabled() 0
48#define trace_hw_mask_param(substream, type, index, prev, curr)
49#define trace_hw_interval_param(substream, type, index, prev, curr)
50#endif
51
40/* 52/*
41 * Compatibility 53 * Compatibility
42 */ 54 */
@@ -181,20 +193,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
181} 193}
182EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); 194EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
183 195
184static inline mm_segment_t snd_enter_user(void)
185{
186 mm_segment_t fs = get_fs();
187 set_fs(get_ds());
188 return fs;
189}
190
191static inline void snd_leave_user(mm_segment_t fs)
192{
193 set_fs(fs);
194}
195
196
197
198int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) 196int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
199{ 197{
200 struct snd_pcm_runtime *runtime; 198 struct snd_pcm_runtime *runtime;
@@ -214,11 +212,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
214 info->subdevices_avail = pstr->substream_count - pstr->substream_opened; 212 info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
215 strlcpy(info->subname, substream->name, sizeof(info->subname)); 213 strlcpy(info->subname, substream->name, sizeof(info->subname));
216 runtime = substream->runtime; 214 runtime = substream->runtime;
217 /* AB: FIXME!!! This is definitely nonsense */ 215
218 if (runtime) {
219 info->sync = runtime->sync;
220 substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
221 }
222 return 0; 216 return 0;
223} 217}
224 218
@@ -255,205 +249,268 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
255 return true; 249 return true;
256} 250}
257 251
258#undef RULES_DEBUG 252static int constrain_mask_params(struct snd_pcm_substream *substream,
259 253 struct snd_pcm_hw_params *params)
260#ifdef RULES_DEBUG
261#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
262static const char * const snd_pcm_hw_param_names[] = {
263 HW_PARAM(ACCESS),
264 HW_PARAM(FORMAT),
265 HW_PARAM(SUBFORMAT),
266 HW_PARAM(SAMPLE_BITS),
267 HW_PARAM(FRAME_BITS),
268 HW_PARAM(CHANNELS),
269 HW_PARAM(RATE),
270 HW_PARAM(PERIOD_TIME),
271 HW_PARAM(PERIOD_SIZE),
272 HW_PARAM(PERIOD_BYTES),
273 HW_PARAM(PERIODS),
274 HW_PARAM(BUFFER_TIME),
275 HW_PARAM(BUFFER_SIZE),
276 HW_PARAM(BUFFER_BYTES),
277 HW_PARAM(TICK_TIME),
278};
279#endif
280
281int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
282 struct snd_pcm_hw_params *params)
283{ 254{
255 struct snd_pcm_hw_constraints *constrs =
256 &substream->runtime->hw_constraints;
257 struct snd_mask *m;
284 unsigned int k; 258 unsigned int k;
285 struct snd_pcm_hardware *hw; 259 struct snd_mask old_mask;
286 struct snd_interval *i = NULL; 260 int changed;
287 struct snd_mask *m = NULL;
288 struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
289 unsigned int rstamps[constrs->rules_num];
290 unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
291 unsigned int stamp = 2;
292 int changed, again;
293
294 params->info = 0;
295 params->fifo_size = 0;
296 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
297 params->msbits = 0;
298 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
299 params->rate_num = 0;
300 params->rate_den = 0;
301 }
302 261
303 for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { 262 for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
304 m = hw_param_mask(params, k); 263 m = hw_param_mask(params, k);
305 if (snd_mask_empty(m)) 264 if (snd_mask_empty(m))
306 return -EINVAL; 265 return -EINVAL;
266
267 /* This parameter is not requested to change by a caller. */
307 if (!(params->rmask & (1 << k))) 268 if (!(params->rmask & (1 << k)))
308 continue; 269 continue;
309#ifdef RULES_DEBUG 270
310 pr_debug("%s = ", snd_pcm_hw_param_names[k]); 271 if (trace_hw_mask_param_enabled())
311 pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); 272 old_mask = *m;
312#endif 273
313 changed = snd_mask_refine(m, constrs_mask(constrs, k)); 274 changed = snd_mask_refine(m, constrs_mask(constrs, k));
314#ifdef RULES_DEBUG
315 pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
316#endif
317 if (changed)
318 params->cmask |= 1 << k;
319 if (changed < 0) 275 if (changed < 0)
320 return changed; 276 return changed;
277 if (changed == 0)
278 continue;
279
280 /* Set corresponding flag so that the caller gets it. */
281 trace_hw_mask_param(substream, k, 0, &old_mask, m);
282 params->cmask |= 1 << k;
321 } 283 }
322 284
285 return 0;
286}
287
288static int constrain_interval_params(struct snd_pcm_substream *substream,
289 struct snd_pcm_hw_params *params)
290{
291 struct snd_pcm_hw_constraints *constrs =
292 &substream->runtime->hw_constraints;
293 struct snd_interval *i;
294 unsigned int k;
295 struct snd_interval old_interval;
296 int changed;
297
323 for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { 298 for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
324 i = hw_param_interval(params, k); 299 i = hw_param_interval(params, k);
325 if (snd_interval_empty(i)) 300 if (snd_interval_empty(i))
326 return -EINVAL; 301 return -EINVAL;
302
303 /* This parameter is not requested to change by a caller. */
327 if (!(params->rmask & (1 << k))) 304 if (!(params->rmask & (1 << k)))
328 continue; 305 continue;
329#ifdef RULES_DEBUG 306
330 pr_debug("%s = ", snd_pcm_hw_param_names[k]); 307 if (trace_hw_interval_param_enabled())
331 if (i->empty) 308 old_interval = *i;
332 pr_cont("empty"); 309
333 else
334 pr_cont("%c%u %u%c",
335 i->openmin ? '(' : '[', i->min,
336 i->max, i->openmax ? ')' : ']');
337 pr_cont(" -> ");
338#endif
339 changed = snd_interval_refine(i, constrs_interval(constrs, k)); 310 changed = snd_interval_refine(i, constrs_interval(constrs, k));
340#ifdef RULES_DEBUG
341 if (i->empty)
342 pr_cont("empty\n");
343 else
344 pr_cont("%c%u %u%c\n",
345 i->openmin ? '(' : '[', i->min,
346 i->max, i->openmax ? ')' : ']');
347#endif
348 if (changed)
349 params->cmask |= 1 << k;
350 if (changed < 0) 311 if (changed < 0)
351 return changed; 312 return changed;
313 if (changed == 0)
314 continue;
315
316 /* Set corresponding flag so that the caller gets it. */
317 trace_hw_interval_param(substream, k, 0, &old_interval, i);
318 params->cmask |= 1 << k;
352 } 319 }
353 320
321 return 0;
322}
323
324static int constrain_params_by_rules(struct snd_pcm_substream *substream,
325 struct snd_pcm_hw_params *params)
326{
327 struct snd_pcm_hw_constraints *constrs =
328 &substream->runtime->hw_constraints;
329 unsigned int k;
330 unsigned int rstamps[constrs->rules_num];
331 unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
332 unsigned int stamp;
333 struct snd_pcm_hw_rule *r;
334 unsigned int d;
335 struct snd_mask old_mask;
336 struct snd_interval old_interval;
337 bool again;
338 int changed;
339
340 /*
341 * Each application of rule has own sequence number.
342 *
343 * Each member of 'rstamps' array represents the sequence number of
344 * recent application of corresponding rule.
345 */
354 for (k = 0; k < constrs->rules_num; k++) 346 for (k = 0; k < constrs->rules_num; k++)
355 rstamps[k] = 0; 347 rstamps[k] = 0;
356 for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) 348
349 /*
350 * Each member of 'vstamps' array represents the sequence number of
351 * recent application of rule in which corresponding parameters were
352 * changed.
353 *
354 * In initial state, elements corresponding to parameters requested by
355 * a caller is 1. For unrequested parameters, corresponding members
356 * have 0 so that the parameters are never changed anymore.
357 */
358 for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
357 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; 359 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
358 do { 360
359 again = 0; 361 /* Due to the above design, actual sequence number starts at 2. */
360 for (k = 0; k < constrs->rules_num; k++) { 362 stamp = 2;
361 struct snd_pcm_hw_rule *r = &constrs->rules[k]; 363retry:
362 unsigned int d; 364 /* Apply all rules in order. */
363 int doit = 0; 365 again = false;
364 if (r->cond && !(r->cond & params->flags)) 366 for (k = 0; k < constrs->rules_num; k++) {
365 continue; 367 r = &constrs->rules[k];
366 for (d = 0; r->deps[d] >= 0; d++) { 368
367 if (vstamps[r->deps[d]] > rstamps[k]) { 369 /*
368 doit = 1; 370 * Check condition bits of this rule. When the rule has
369 break; 371 * some condition bits, parameter without the bits is
370 } 372 * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
371 } 373 * is an example of the condition bits.
372 if (!doit) 374 */
373 continue; 375 if (r->cond && !(r->cond & params->flags))
374#ifdef RULES_DEBUG 376 continue;
375 pr_debug("Rule %d [%p]: ", k, r->func); 377
376 if (r->var >= 0) { 378 /*
377 pr_cont("%s = ", snd_pcm_hw_param_names[r->var]); 379 * The 'deps' array includes maximum three dependencies
378 if (hw_is_mask(r->var)) { 380 * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
379 m = hw_param_mask(params, r->var); 381 * member of this array is a sentinel and should be
380 pr_cont("%x", *m->bits); 382 * negative value.
381 } else { 383 *
382 i = hw_param_interval(params, r->var); 384 * This rule should be processed in this time when dependent
383 if (i->empty) 385 * parameters were changed at former applications of the other
384 pr_cont("empty"); 386 * rules.
385 else 387 */
386 pr_cont("%c%u %u%c", 388 for (d = 0; r->deps[d] >= 0; d++) {
387 i->openmin ? '(' : '[', i->min, 389 if (vstamps[r->deps[d]] > rstamps[k])
388 i->max, i->openmax ? ')' : ']'); 390 break;
389 } 391 }
390 } 392 if (r->deps[d] < 0)
391#endif 393 continue;
392 changed = r->func(params, r); 394
393#ifdef RULES_DEBUG 395 if (trace_hw_mask_param_enabled()) {
394 if (r->var >= 0) { 396 if (hw_is_mask(r->var))
395 pr_cont(" -> "); 397 old_mask = *hw_param_mask(params, r->var);
396 if (hw_is_mask(r->var)) 398 }
397 pr_cont("%x", *m->bits); 399 if (trace_hw_interval_param_enabled()) {
398 else { 400 if (hw_is_interval(r->var))
399 if (i->empty) 401 old_interval = *hw_param_interval(params, r->var);
400 pr_cont("empty"); 402 }
401 else 403
402 pr_cont("%c%u %u%c", 404 changed = r->func(params, r);
403 i->openmin ? '(' : '[', i->min, 405 if (changed < 0)
404 i->max, i->openmax ? ')' : ']'); 406 return changed;
405 } 407
408 /*
409 * When the parameter is changed, notify it to the caller
410 * by corresponding returned bit, then preparing for next
411 * iteration.
412 */
413 if (changed && r->var >= 0) {
414 if (hw_is_mask(r->var)) {
415 trace_hw_mask_param(substream, r->var,
416 k + 1, &old_mask,
417 hw_param_mask(params, r->var));
406 } 418 }
407 pr_cont("\n"); 419 if (hw_is_interval(r->var)) {
408#endif 420 trace_hw_interval_param(substream, r->var,
409 rstamps[k] = stamp; 421 k + 1, &old_interval,
410 if (changed && r->var >= 0) { 422 hw_param_interval(params, r->var));
411 params->cmask |= (1 << r->var);
412 vstamps[r->var] = stamp;
413 again = 1;
414 } 423 }
415 if (changed < 0) 424
416 return changed; 425 params->cmask |= (1 << r->var);
417 stamp++; 426 vstamps[r->var] = stamp;
427 again = true;
418 } 428 }
419 } while (again); 429
430 rstamps[k] = stamp++;
431 }
432
433 /* Iterate to evaluate all rules till no parameters are changed. */
434 if (again)
435 goto retry;
436
437 return 0;
438}
439
440static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
441 struct snd_pcm_hw_params *params)
442{
443 const struct snd_interval *i;
444 const struct snd_mask *m;
445 int err;
446
420 if (!params->msbits) { 447 if (!params->msbits) {
421 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 448 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
422 if (snd_interval_single(i)) 449 if (snd_interval_single(i))
423 params->msbits = snd_interval_value(i); 450 params->msbits = snd_interval_value(i);
424 } 451 }
425 452
426 if (!params->rate_den) { 453 if (!params->rate_den) {
427 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 454 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
428 if (snd_interval_single(i)) { 455 if (snd_interval_single(i)) {
429 params->rate_num = snd_interval_value(i); 456 params->rate_num = snd_interval_value(i);
430 params->rate_den = 1; 457 params->rate_den = 1;
431 } 458 }
432 } 459 }
433 460
434 hw = &substream->runtime->hw; 461 if (!params->fifo_size) {
462 m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
463 i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
464 if (snd_mask_single(m) && snd_interval_single(i)) {
465 err = substream->ops->ioctl(substream,
466 SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
467 if (err < 0)
468 return err;
469 }
470 }
471
435 if (!params->info) { 472 if (!params->info) {
436 params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | 473 params->info = substream->runtime->hw.info;
437 SNDRV_PCM_INFO_DRAIN_TRIGGER); 474 params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
475 SNDRV_PCM_INFO_DRAIN_TRIGGER);
438 if (!hw_support_mmap(substream)) 476 if (!hw_support_mmap(substream))
439 params->info &= ~(SNDRV_PCM_INFO_MMAP | 477 params->info &= ~(SNDRV_PCM_INFO_MMAP |
440 SNDRV_PCM_INFO_MMAP_VALID); 478 SNDRV_PCM_INFO_MMAP_VALID);
441 } 479 }
442 if (!params->fifo_size) { 480
443 m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 481 return 0;
444 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 482}
445 if (snd_mask_min(m) == snd_mask_max(m) && 483
446 snd_interval_min(i) == snd_interval_max(i)) { 484int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
447 changed = substream->ops->ioctl(substream, 485 struct snd_pcm_hw_params *params)
448 SNDRV_PCM_IOCTL1_FIFO_SIZE, params); 486{
449 if (changed < 0) 487 int err;
450 return changed; 488
451 } 489 params->info = 0;
490 params->fifo_size = 0;
491 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
492 params->msbits = 0;
493 if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
494 params->rate_num = 0;
495 params->rate_den = 0;
452 } 496 }
497
498 err = constrain_mask_params(substream, params);
499 if (err < 0)
500 return err;
501
502 err = constrain_interval_params(substream, params);
503 if (err < 0)
504 return err;
505
506 err = constrain_params_by_rules(substream, params);
507 if (err < 0)
508 return err;
509
453 params->rmask = 0; 510 params->rmask = 0;
511
454 return 0; 512 return 0;
455} 513}
456
457EXPORT_SYMBOL(snd_pcm_hw_refine); 514EXPORT_SYMBOL(snd_pcm_hw_refine);
458 515
459static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, 516static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
@@ -467,11 +524,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
467 return PTR_ERR(params); 524 return PTR_ERR(params);
468 525
469 err = snd_pcm_hw_refine(substream, params); 526 err = snd_pcm_hw_refine(substream, params);
470 if (copy_to_user(_params, params, sizeof(*params))) { 527 if (err < 0)
471 if (!err) 528 goto end;
472 err = -EFAULT; 529
473 } 530 err = fixup_unreferenced_params(substream, params);
531 if (err < 0)
532 goto end;
474 533
534 if (copy_to_user(_params, params, sizeof(*params)))
535 err = -EFAULT;
536end:
475 kfree(params); 537 kfree(params);
476 return err; 538 return err;
477} 539}
@@ -509,6 +571,70 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
509#endif 571#endif
510} 572}
511 573
574/**
575 * snd_pcm_hw_param_choose - choose a configuration defined by @params
576 * @pcm: PCM instance
577 * @params: the hw_params instance
578 *
579 * Choose one configuration from configuration space defined by @params.
580 * The configuration chosen is that obtained fixing in this order:
581 * first access, first format, first subformat, min channels,
582 * min rate, min period time, max buffer size, min tick time
583 *
584 * Return: Zero if successful, or a negative error code on failure.
585 */
586static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
587 struct snd_pcm_hw_params *params)
588{
589 static const int vars[] = {
590 SNDRV_PCM_HW_PARAM_ACCESS,
591 SNDRV_PCM_HW_PARAM_FORMAT,
592 SNDRV_PCM_HW_PARAM_SUBFORMAT,
593 SNDRV_PCM_HW_PARAM_CHANNELS,
594 SNDRV_PCM_HW_PARAM_RATE,
595 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
596 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
597 SNDRV_PCM_HW_PARAM_TICK_TIME,
598 -1
599 };
600 const int *v;
601 struct snd_mask old_mask;
602 struct snd_interval old_interval;
603 int changed;
604
605 for (v = vars; *v != -1; v++) {
606 /* Keep old parameter to trace. */
607 if (trace_hw_mask_param_enabled()) {
608 if (hw_is_mask(*v))
609 old_mask = *hw_param_mask(params, *v);
610 }
611 if (trace_hw_interval_param_enabled()) {
612 if (hw_is_interval(*v))
613 old_interval = *hw_param_interval(params, *v);
614 }
615 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
616 changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
617 else
618 changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
619 if (snd_BUG_ON(changed < 0))
620 return changed;
621 if (changed == 0)
622 continue;
623
624 /* Trace the changed parameter. */
625 if (hw_is_mask(*v)) {
626 trace_hw_mask_param(pcm, *v, 0, &old_mask,
627 hw_param_mask(params, *v));
628 }
629 if (hw_is_interval(*v)) {
630 trace_hw_interval_param(pcm, *v, 0, &old_interval,
631 hw_param_interval(params, *v));
632 }
633 }
634
635 return 0;
636}
637
512static int snd_pcm_hw_params(struct snd_pcm_substream *substream, 638static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
513 struct snd_pcm_hw_params *params) 639 struct snd_pcm_hw_params *params)
514{ 640{
@@ -546,6 +672,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
546 if (err < 0) 672 if (err < 0)
547 goto _error; 673 goto _error;
548 674
675 err = fixup_unreferenced_params(substream, params);
676 if (err < 0)
677 goto _error;
678
549 if (substream->ops->hw_params != NULL) { 679 if (substream->ops->hw_params != NULL) {
550 err = substream->ops->hw_params(substream, params); 680 err = substream->ops->hw_params(substream, params);
551 if (err < 0) 681 if (err < 0)
@@ -621,11 +751,12 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
621 return PTR_ERR(params); 751 return PTR_ERR(params);
622 752
623 err = snd_pcm_hw_params(substream, params); 753 err = snd_pcm_hw_params(substream, params);
624 if (copy_to_user(_params, params, sizeof(*params))) { 754 if (err < 0)
625 if (!err) 755 goto end;
626 err = -EFAULT;
627 }
628 756
757 if (copy_to_user(_params, params, sizeof(*params)))
758 err = -EFAULT;
759end:
629 kfree(params); 760 kfree(params);
630 return err; 761 return err;
631} 762}
@@ -1081,6 +1212,7 @@ static const struct action_ops snd_pcm_action_start = {
1081 * @substream: the PCM substream instance 1212 * @substream: the PCM substream instance
1082 * 1213 *
1083 * Return: Zero if successful, or a negative error code. 1214 * Return: Zero if successful, or a negative error code.
1215 * The stream lock must be acquired before calling this function.
1084 */ 1216 */
1085int snd_pcm_start(struct snd_pcm_substream *substream) 1217int snd_pcm_start(struct snd_pcm_substream *substream)
1086{ 1218{
@@ -1088,6 +1220,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream)
1088 SNDRV_PCM_STATE_RUNNING); 1220 SNDRV_PCM_STATE_RUNNING);
1089} 1221}
1090 1222
1223/* take the stream lock and start the streams */
1224static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
1225{
1226 return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
1227 SNDRV_PCM_STATE_RUNNING);
1228}
1229
1091/* 1230/*
1092 * stop callbacks 1231 * stop callbacks
1093 */ 1232 */
@@ -1139,7 +1278,6 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
1139{ 1278{
1140 return snd_pcm_action(&snd_pcm_action_stop, substream, state); 1279 return snd_pcm_action(&snd_pcm_action_stop, substream, state);
1141} 1280}
1142
1143EXPORT_SYMBOL(snd_pcm_stop); 1281EXPORT_SYMBOL(snd_pcm_stop);
1144 1282
1145/** 1283/**
@@ -1314,7 +1452,6 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
1314 snd_pcm_stream_unlock_irqrestore(substream, flags); 1452 snd_pcm_stream_unlock_irqrestore(substream, flags);
1315 return err; 1453 return err;
1316} 1454}
1317
1318EXPORT_SYMBOL(snd_pcm_suspend); 1455EXPORT_SYMBOL(snd_pcm_suspend);
1319 1456
1320/** 1457/**
@@ -1346,7 +1483,6 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
1346 } 1483 }
1347 return 0; 1484 return 0;
1348} 1485}
1349
1350EXPORT_SYMBOL(snd_pcm_suspend_all); 1486EXPORT_SYMBOL(snd_pcm_suspend_all);
1351 1487
1352/* resume */ 1488/* resume */
@@ -1397,14 +1533,7 @@ static const struct action_ops snd_pcm_action_resume = {
1397 1533
1398static int snd_pcm_resume(struct snd_pcm_substream *substream) 1534static int snd_pcm_resume(struct snd_pcm_substream *substream)
1399{ 1535{
1400 struct snd_card *card = substream->pcm->card; 1536 return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1401 int res;
1402
1403 snd_power_lock(card);
1404 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1405 res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1406 snd_power_unlock(card);
1407 return res;
1408} 1537}
1409 1538
1410#else 1539#else
@@ -1423,17 +1552,9 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
1423 */ 1552 */
1424static int snd_pcm_xrun(struct snd_pcm_substream *substream) 1553static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1425{ 1554{
1426 struct snd_card *card = substream->pcm->card;
1427 struct snd_pcm_runtime *runtime = substream->runtime; 1555 struct snd_pcm_runtime *runtime = substream->runtime;
1428 int result; 1556 int result;
1429 1557
1430 snd_power_lock(card);
1431 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1432 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1433 if (result < 0)
1434 goto _unlock;
1435 }
1436
1437 snd_pcm_stream_lock_irq(substream); 1558 snd_pcm_stream_lock_irq(substream);
1438 switch (runtime->status->state) { 1559 switch (runtime->status->state) {
1439 case SNDRV_PCM_STATE_XRUN: 1560 case SNDRV_PCM_STATE_XRUN:
@@ -1446,8 +1567,6 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1446 result = -EBADFD; 1567 result = -EBADFD;
1447 } 1568 }
1448 snd_pcm_stream_unlock_irq(substream); 1569 snd_pcm_stream_unlock_irq(substream);
1449 _unlock:
1450 snd_power_unlock(card);
1451 return result; 1570 return result;
1452} 1571}
1453 1572
@@ -1551,8 +1670,6 @@ static const struct action_ops snd_pcm_action_prepare = {
1551static int snd_pcm_prepare(struct snd_pcm_substream *substream, 1670static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1552 struct file *file) 1671 struct file *file)
1553{ 1672{
1554 int res;
1555 struct snd_card *card = substream->pcm->card;
1556 int f_flags; 1673 int f_flags;
1557 1674
1558 if (file) 1675 if (file)
@@ -1560,12 +1677,19 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1560 else 1677 else
1561 f_flags = substream->f_flags; 1678 f_flags = substream->f_flags;
1562 1679
1563 snd_power_lock(card); 1680 snd_pcm_stream_lock_irq(substream);
1564 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) 1681 switch (substream->runtime->status->state) {
1565 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, 1682 case SNDRV_PCM_STATE_PAUSED:
1566 substream, f_flags); 1683 snd_pcm_pause(substream, 0);
1567 snd_power_unlock(card); 1684 /* fallthru */
1568 return res; 1685 case SNDRV_PCM_STATE_SUSPENDED:
1686 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1687 break;
1688 }
1689 snd_pcm_stream_unlock_irq(substream);
1690
1691 return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
1692 substream, f_flags);
1569} 1693}
1570 1694
1571/* 1695/*
@@ -1662,15 +1786,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1662 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 1786 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1663 return -EBADFD; 1787 return -EBADFD;
1664 1788
1665 snd_power_lock(card);
1666 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1667 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1668 if (result < 0) {
1669 snd_power_unlock(card);
1670 return result;
1671 }
1672 }
1673
1674 if (file) { 1789 if (file) {
1675 if (file->f_flags & O_NONBLOCK) 1790 if (file->f_flags & O_NONBLOCK)
1676 nonblock = 1; 1791 nonblock = 1;
@@ -1753,7 +1868,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1753 unlock: 1868 unlock:
1754 snd_pcm_stream_unlock_irq(substream); 1869 snd_pcm_stream_unlock_irq(substream);
1755 up_read(&snd_pcm_link_rwsem); 1870 up_read(&snd_pcm_link_rwsem);
1756 snd_power_unlock(card);
1757 1871
1758 return result; 1872 return result;
1759} 1873}
@@ -1773,8 +1887,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
1773 runtime = substream->runtime; 1887 runtime = substream->runtime;
1774 1888
1775 if (runtime->status->state == SNDRV_PCM_STATE_OPEN || 1889 if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
1776 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || 1890 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
1777 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
1778 return -EBADFD; 1891 return -EBADFD;
1779 1892
1780 snd_pcm_stream_lock_irq(substream); 1893 snd_pcm_stream_lock_irq(substream);
@@ -1940,7 +2053,8 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
1940 struct snd_pcm_hw_rule *rule) 2053 struct snd_pcm_hw_rule *rule)
1941{ 2054{
1942 unsigned int k; 2055 unsigned int k;
1943 struct snd_interval *i = hw_param_interval(params, rule->deps[0]); 2056 const struct snd_interval *i =
2057 hw_param_interval_c(params, rule->deps[0]);
1944 struct snd_mask m; 2058 struct snd_mask m;
1945 struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 2059 struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1946 snd_mask_any(&m); 2060 snd_mask_any(&m);
@@ -1986,8 +2100,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
1986#error "Change this table" 2100#error "Change this table"
1987#endif 2101#endif
1988 2102
1989static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 2103static const unsigned int rates[] = {
1990 48000, 64000, 88200, 96000, 176400, 192000 }; 2104 5512, 8000, 11025, 16000, 22050, 32000, 44100,
2105 48000, 64000, 88200, 96000, 176400, 192000
2106};
1991 2107
1992const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { 2108const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
1993 .count = ARRAY_SIZE(rates), 2109 .count = ARRAY_SIZE(rates),
@@ -2250,7 +2366,6 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2250 } 2366 }
2251 snd_pcm_detach_substream(substream); 2367 snd_pcm_detach_substream(substream);
2252} 2368}
2253
2254EXPORT_SYMBOL(snd_pcm_release_substream); 2369EXPORT_SYMBOL(snd_pcm_release_substream);
2255 2370
2256int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, 2371int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
@@ -2292,7 +2407,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2292 snd_pcm_release_substream(substream); 2407 snd_pcm_release_substream(substream);
2293 return err; 2408 return err;
2294} 2409}
2295
2296EXPORT_SYMBOL(snd_pcm_open_substream); 2410EXPORT_SYMBOL(snd_pcm_open_substream);
2297 2411
2298static int snd_pcm_open_file(struct file *file, 2412static int snd_pcm_open_file(struct file *file,
@@ -2428,50 +2542,84 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
2428 return 0; 2542 return 0;
2429} 2543}
2430 2544
2431static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, 2545/* check and update PCM state; return 0 or a negative error
2432 snd_pcm_uframes_t frames) 2546 * call this inside PCM lock
2547 */
2548static int do_pcm_hwsync(struct snd_pcm_substream *substream)
2433{ 2549{
2434 struct snd_pcm_runtime *runtime = substream->runtime; 2550 switch (substream->runtime->status->state) {
2435 snd_pcm_sframes_t appl_ptr;
2436 snd_pcm_sframes_t ret;
2437 snd_pcm_sframes_t hw_avail;
2438
2439 if (frames == 0)
2440 return 0;
2441
2442 snd_pcm_stream_lock_irq(substream);
2443 switch (runtime->status->state) {
2444 case SNDRV_PCM_STATE_PREPARED:
2445 break;
2446 case SNDRV_PCM_STATE_DRAINING: 2551 case SNDRV_PCM_STATE_DRAINING:
2447 case SNDRV_PCM_STATE_RUNNING: 2552 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2448 if (snd_pcm_update_hw_ptr(substream) >= 0) 2553 return -EBADFD;
2449 break;
2450 /* Fall through */ 2554 /* Fall through */
2451 case SNDRV_PCM_STATE_XRUN: 2555 case SNDRV_PCM_STATE_RUNNING:
2452 ret = -EPIPE; 2556 return snd_pcm_update_hw_ptr(substream);
2453 goto __end; 2557 case SNDRV_PCM_STATE_PREPARED:
2558 case SNDRV_PCM_STATE_PAUSED:
2559 return 0;
2454 case SNDRV_PCM_STATE_SUSPENDED: 2560 case SNDRV_PCM_STATE_SUSPENDED:
2455 ret = -ESTRPIPE; 2561 return -ESTRPIPE;
2456 goto __end; 2562 case SNDRV_PCM_STATE_XRUN:
2563 return -EPIPE;
2457 default: 2564 default:
2458 ret = -EBADFD; 2565 return -EBADFD;
2459 goto __end;
2460 } 2566 }
2567}
2461 2568
2462 hw_avail = snd_pcm_playback_hw_avail(runtime); 2569/* increase the appl_ptr; returns the processed frames or a negative error */
2463 if (hw_avail <= 0) { 2570static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
2464 ret = 0; 2571 snd_pcm_uframes_t frames,
2465 goto __end; 2572 snd_pcm_sframes_t avail)
2466 } 2573{
2467 if (frames > (snd_pcm_uframes_t)hw_avail) 2574 struct snd_pcm_runtime *runtime = substream->runtime;
2468 frames = hw_avail; 2575 snd_pcm_sframes_t appl_ptr;
2576 int ret;
2577
2578 if (avail <= 0)
2579 return 0;
2580 if (frames > (snd_pcm_uframes_t)avail)
2581 frames = avail;
2582 appl_ptr = runtime->control->appl_ptr + frames;
2583 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2584 appl_ptr -= runtime->boundary;
2585 ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2586 return ret < 0 ? ret : frames;
2587}
2588
2589/* decrease the appl_ptr; returns the processed frames or a negative error */
2590static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
2591 snd_pcm_uframes_t frames,
2592 snd_pcm_sframes_t avail)
2593{
2594 struct snd_pcm_runtime *runtime = substream->runtime;
2595 snd_pcm_sframes_t appl_ptr;
2596 int ret;
2597
2598 if (avail <= 0)
2599 return 0;
2600 if (frames > (snd_pcm_uframes_t)avail)
2601 frames = avail;
2469 appl_ptr = runtime->control->appl_ptr - frames; 2602 appl_ptr = runtime->control->appl_ptr - frames;
2470 if (appl_ptr < 0) 2603 if (appl_ptr < 0)
2471 appl_ptr += runtime->boundary; 2604 appl_ptr += runtime->boundary;
2472 runtime->control->appl_ptr = appl_ptr; 2605 ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2473 ret = frames; 2606 return ret < 0 ? ret : frames;
2474 __end: 2607}
2608
2609static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
2610 snd_pcm_uframes_t frames)
2611{
2612 struct snd_pcm_runtime *runtime = substream->runtime;
2613 snd_pcm_sframes_t ret;
2614
2615 if (frames == 0)
2616 return 0;
2617
2618 snd_pcm_stream_lock_irq(substream);
2619 ret = do_pcm_hwsync(substream);
2620 if (!ret)
2621 ret = rewind_appl_ptr(substream, frames,
2622 snd_pcm_playback_hw_avail(runtime));
2475 snd_pcm_stream_unlock_irq(substream); 2623 snd_pcm_stream_unlock_irq(substream);
2476 return ret; 2624 return ret;
2477} 2625}
@@ -2480,46 +2628,16 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
2480 snd_pcm_uframes_t frames) 2628 snd_pcm_uframes_t frames)
2481{ 2629{
2482 struct snd_pcm_runtime *runtime = substream->runtime; 2630 struct snd_pcm_runtime *runtime = substream->runtime;
2483 snd_pcm_sframes_t appl_ptr;
2484 snd_pcm_sframes_t ret; 2631 snd_pcm_sframes_t ret;
2485 snd_pcm_sframes_t hw_avail;
2486 2632
2487 if (frames == 0) 2633 if (frames == 0)
2488 return 0; 2634 return 0;
2489 2635
2490 snd_pcm_stream_lock_irq(substream); 2636 snd_pcm_stream_lock_irq(substream);
2491 switch (runtime->status->state) { 2637 ret = do_pcm_hwsync(substream);
2492 case SNDRV_PCM_STATE_PREPARED: 2638 if (!ret)
2493 case SNDRV_PCM_STATE_DRAINING: 2639 ret = rewind_appl_ptr(substream, frames,
2494 break; 2640 snd_pcm_capture_hw_avail(runtime));
2495 case SNDRV_PCM_STATE_RUNNING:
2496 if (snd_pcm_update_hw_ptr(substream) >= 0)
2497 break;
2498 /* Fall through */
2499 case SNDRV_PCM_STATE_XRUN:
2500 ret = -EPIPE;
2501 goto __end;
2502 case SNDRV_PCM_STATE_SUSPENDED:
2503 ret = -ESTRPIPE;
2504 goto __end;
2505 default:
2506 ret = -EBADFD;
2507 goto __end;
2508 }
2509
2510 hw_avail = snd_pcm_capture_hw_avail(runtime);
2511 if (hw_avail <= 0) {
2512 ret = 0;
2513 goto __end;
2514 }
2515 if (frames > (snd_pcm_uframes_t)hw_avail)
2516 frames = hw_avail;
2517 appl_ptr = runtime->control->appl_ptr - frames;
2518 if (appl_ptr < 0)
2519 appl_ptr += runtime->boundary;
2520 runtime->control->appl_ptr = appl_ptr;
2521 ret = frames;
2522 __end:
2523 snd_pcm_stream_unlock_irq(substream); 2641 snd_pcm_stream_unlock_irq(substream);
2524 return ret; 2642 return ret;
2525} 2643}
@@ -2528,47 +2646,16 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
2528 snd_pcm_uframes_t frames) 2646 snd_pcm_uframes_t frames)
2529{ 2647{
2530 struct snd_pcm_runtime *runtime = substream->runtime; 2648 struct snd_pcm_runtime *runtime = substream->runtime;
2531 snd_pcm_sframes_t appl_ptr;
2532 snd_pcm_sframes_t ret; 2649 snd_pcm_sframes_t ret;
2533 snd_pcm_sframes_t avail;
2534 2650
2535 if (frames == 0) 2651 if (frames == 0)
2536 return 0; 2652 return 0;
2537 2653
2538 snd_pcm_stream_lock_irq(substream); 2654 snd_pcm_stream_lock_irq(substream);
2539 switch (runtime->status->state) { 2655 ret = do_pcm_hwsync(substream);
2540 case SNDRV_PCM_STATE_PREPARED: 2656 if (!ret)
2541 case SNDRV_PCM_STATE_PAUSED: 2657 ret = forward_appl_ptr(substream, frames,
2542 break; 2658 snd_pcm_playback_avail(runtime));
2543 case SNDRV_PCM_STATE_DRAINING:
2544 case SNDRV_PCM_STATE_RUNNING:
2545 if (snd_pcm_update_hw_ptr(substream) >= 0)
2546 break;
2547 /* Fall through */
2548 case SNDRV_PCM_STATE_XRUN:
2549 ret = -EPIPE;
2550 goto __end;
2551 case SNDRV_PCM_STATE_SUSPENDED:
2552 ret = -ESTRPIPE;
2553 goto __end;
2554 default:
2555 ret = -EBADFD;
2556 goto __end;
2557 }
2558
2559 avail = snd_pcm_playback_avail(runtime);
2560 if (avail <= 0) {
2561 ret = 0;
2562 goto __end;
2563 }
2564 if (frames > (snd_pcm_uframes_t)avail)
2565 frames = avail;
2566 appl_ptr = runtime->control->appl_ptr + frames;
2567 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2568 appl_ptr -= runtime->boundary;
2569 runtime->control->appl_ptr = appl_ptr;
2570 ret = frames;
2571 __end:
2572 snd_pcm_stream_unlock_irq(substream); 2659 snd_pcm_stream_unlock_irq(substream);
2573 return ret; 2660 return ret;
2574} 2661}
@@ -2577,123 +2664,47 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
2577 snd_pcm_uframes_t frames) 2664 snd_pcm_uframes_t frames)
2578{ 2665{
2579 struct snd_pcm_runtime *runtime = substream->runtime; 2666 struct snd_pcm_runtime *runtime = substream->runtime;
2580 snd_pcm_sframes_t appl_ptr;
2581 snd_pcm_sframes_t ret; 2667 snd_pcm_sframes_t ret;
2582 snd_pcm_sframes_t avail;
2583 2668
2584 if (frames == 0) 2669 if (frames == 0)
2585 return 0; 2670 return 0;
2586 2671
2587 snd_pcm_stream_lock_irq(substream); 2672 snd_pcm_stream_lock_irq(substream);
2588 switch (runtime->status->state) { 2673 ret = do_pcm_hwsync(substream);
2589 case SNDRV_PCM_STATE_PREPARED: 2674 if (!ret)
2590 case SNDRV_PCM_STATE_DRAINING: 2675 ret = forward_appl_ptr(substream, frames,
2591 case SNDRV_PCM_STATE_PAUSED: 2676 snd_pcm_capture_avail(runtime));
2592 break;
2593 case SNDRV_PCM_STATE_RUNNING:
2594 if (snd_pcm_update_hw_ptr(substream) >= 0)
2595 break;
2596 /* Fall through */
2597 case SNDRV_PCM_STATE_XRUN:
2598 ret = -EPIPE;
2599 goto __end;
2600 case SNDRV_PCM_STATE_SUSPENDED:
2601 ret = -ESTRPIPE;
2602 goto __end;
2603 default:
2604 ret = -EBADFD;
2605 goto __end;
2606 }
2607
2608 avail = snd_pcm_capture_avail(runtime);
2609 if (avail <= 0) {
2610 ret = 0;
2611 goto __end;
2612 }
2613 if (frames > (snd_pcm_uframes_t)avail)
2614 frames = avail;
2615 appl_ptr = runtime->control->appl_ptr + frames;
2616 if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2617 appl_ptr -= runtime->boundary;
2618 runtime->control->appl_ptr = appl_ptr;
2619 ret = frames;
2620 __end:
2621 snd_pcm_stream_unlock_irq(substream); 2677 snd_pcm_stream_unlock_irq(substream);
2622 return ret; 2678 return ret;
2623} 2679}
2624 2680
2625static int snd_pcm_hwsync(struct snd_pcm_substream *substream) 2681static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
2626{ 2682{
2627 struct snd_pcm_runtime *runtime = substream->runtime;
2628 int err; 2683 int err;
2629 2684
2630 snd_pcm_stream_lock_irq(substream); 2685 snd_pcm_stream_lock_irq(substream);
2631 switch (runtime->status->state) { 2686 err = do_pcm_hwsync(substream);
2632 case SNDRV_PCM_STATE_DRAINING:
2633 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2634 goto __badfd;
2635 /* Fall through */
2636 case SNDRV_PCM_STATE_RUNNING:
2637 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
2638 break;
2639 /* Fall through */
2640 case SNDRV_PCM_STATE_PREPARED:
2641 err = 0;
2642 break;
2643 case SNDRV_PCM_STATE_SUSPENDED:
2644 err = -ESTRPIPE;
2645 break;
2646 case SNDRV_PCM_STATE_XRUN:
2647 err = -EPIPE;
2648 break;
2649 default:
2650 __badfd:
2651 err = -EBADFD;
2652 break;
2653 }
2654 snd_pcm_stream_unlock_irq(substream); 2687 snd_pcm_stream_unlock_irq(substream);
2655 return err; 2688 return err;
2656} 2689}
2657 2690
2658static int snd_pcm_delay(struct snd_pcm_substream *substream, 2691static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
2659 snd_pcm_sframes_t __user *res)
2660{ 2692{
2661 struct snd_pcm_runtime *runtime = substream->runtime; 2693 struct snd_pcm_runtime *runtime = substream->runtime;
2662 int err; 2694 int err;
2663 snd_pcm_sframes_t n = 0; 2695 snd_pcm_sframes_t n = 0;
2664 2696
2665 snd_pcm_stream_lock_irq(substream); 2697 snd_pcm_stream_lock_irq(substream);
2666 switch (runtime->status->state) { 2698 err = do_pcm_hwsync(substream);
2667 case SNDRV_PCM_STATE_DRAINING: 2699 if (!err) {
2668 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2669 goto __badfd;
2670 /* Fall through */
2671 case SNDRV_PCM_STATE_RUNNING:
2672 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
2673 break;
2674 /* Fall through */
2675 case SNDRV_PCM_STATE_PREPARED:
2676 case SNDRV_PCM_STATE_SUSPENDED:
2677 err = 0;
2678 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 2700 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2679 n = snd_pcm_playback_hw_avail(runtime); 2701 n = snd_pcm_playback_hw_avail(runtime);
2680 else 2702 else
2681 n = snd_pcm_capture_avail(runtime); 2703 n = snd_pcm_capture_avail(runtime);
2682 n += runtime->delay; 2704 n += runtime->delay;
2683 break;
2684 case SNDRV_PCM_STATE_XRUN:
2685 err = -EPIPE;
2686 break;
2687 default:
2688 __badfd:
2689 err = -EBADFD;
2690 break;
2691 } 2705 }
2692 snd_pcm_stream_unlock_irq(substream); 2706 snd_pcm_stream_unlock_irq(substream);
2693 if (!err) 2707 return err < 0 ? err : n;
2694 if (put_user(n, res))
2695 err = -EFAULT;
2696 return err;
2697} 2708}
2698 2709
2699static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, 2710static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
@@ -2718,10 +2729,16 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2718 return err; 2729 return err;
2719 } 2730 }
2720 snd_pcm_stream_lock_irq(substream); 2731 snd_pcm_stream_lock_irq(substream);
2721 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) 2732 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
2722 control->appl_ptr = sync_ptr.c.control.appl_ptr; 2733 err = pcm_lib_apply_appl_ptr(substream,
2723 else 2734 sync_ptr.c.control.appl_ptr);
2735 if (err < 0) {
2736 snd_pcm_stream_unlock_irq(substream);
2737 return err;
2738 }
2739 } else {
2724 sync_ptr.c.control.appl_ptr = control->appl_ptr; 2740 sync_ptr.c.control.appl_ptr = control->appl_ptr;
2741 }
2725 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 2742 if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
2726 control->avail_min = sync_ptr.c.control.avail_min; 2743 control->avail_min = sync_ptr.c.control.avail_min;
2727 else 2744 else
@@ -2749,10 +2766,12 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
2749 return 0; 2766 return 0;
2750} 2767}
2751 2768
2752static int snd_pcm_common_ioctl1(struct file *file, 2769static int snd_pcm_common_ioctl(struct file *file,
2753 struct snd_pcm_substream *substream, 2770 struct snd_pcm_substream *substream,
2754 unsigned int cmd, void __user *arg) 2771 unsigned int cmd, void __user *arg)
2755{ 2772{
2773 struct snd_pcm_file *pcm_file = file->private_data;
2774
2756 switch (cmd) { 2775 switch (cmd) {
2757 case SNDRV_PCM_IOCTL_PVERSION: 2776 case SNDRV_PCM_IOCTL_PVERSION:
2758 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; 2777 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -2762,6 +2781,11 @@ static int snd_pcm_common_ioctl1(struct file *file,
2762 return 0; 2781 return 0;
2763 case SNDRV_PCM_IOCTL_TTSTAMP: 2782 case SNDRV_PCM_IOCTL_TTSTAMP:
2764 return snd_pcm_tstamp(substream, arg); 2783 return snd_pcm_tstamp(substream, arg);
2784 case SNDRV_PCM_IOCTL_USER_PVERSION:
2785 if (get_user(pcm_file->user_pversion,
2786 (unsigned int __user *)arg))
2787 return -EFAULT;
2788 return 0;
2765 case SNDRV_PCM_IOCTL_HW_REFINE: 2789 case SNDRV_PCM_IOCTL_HW_REFINE:
2766 return snd_pcm_hw_refine_user(substream, arg); 2790 return snd_pcm_hw_refine_user(substream, arg);
2767 case SNDRV_PCM_IOCTL_HW_PARAMS: 2791 case SNDRV_PCM_IOCTL_HW_PARAMS:
@@ -2781,7 +2805,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
2781 case SNDRV_PCM_IOCTL_RESET: 2805 case SNDRV_PCM_IOCTL_RESET:
2782 return snd_pcm_reset(substream); 2806 return snd_pcm_reset(substream);
2783 case SNDRV_PCM_IOCTL_START: 2807 case SNDRV_PCM_IOCTL_START:
2784 return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); 2808 return snd_pcm_start_lock_irq(substream);
2785 case SNDRV_PCM_IOCTL_LINK: 2809 case SNDRV_PCM_IOCTL_LINK:
2786 return snd_pcm_link(substream, (int)(unsigned long) arg); 2810 return snd_pcm_link(substream, (int)(unsigned long) arg);
2787 case SNDRV_PCM_IOCTL_UNLINK: 2811 case SNDRV_PCM_IOCTL_UNLINK:
@@ -2793,7 +2817,16 @@ static int snd_pcm_common_ioctl1(struct file *file,
2793 case SNDRV_PCM_IOCTL_HWSYNC: 2817 case SNDRV_PCM_IOCTL_HWSYNC:
2794 return snd_pcm_hwsync(substream); 2818 return snd_pcm_hwsync(substream);
2795 case SNDRV_PCM_IOCTL_DELAY: 2819 case SNDRV_PCM_IOCTL_DELAY:
2796 return snd_pcm_delay(substream, arg); 2820 {
2821 snd_pcm_sframes_t delay = snd_pcm_delay(substream);
2822 snd_pcm_sframes_t __user *res = arg;
2823
2824 if (delay < 0)
2825 return delay;
2826 if (put_user(delay, res))
2827 return -EFAULT;
2828 return 0;
2829 }
2797 case SNDRV_PCM_IOCTL_SYNC_PTR: 2830 case SNDRV_PCM_IOCTL_SYNC_PTR:
2798 return snd_pcm_sync_ptr(substream, arg); 2831 return snd_pcm_sync_ptr(substream, arg);
2799#ifdef CONFIG_SND_SUPPORT_OLD_API 2832#ifdef CONFIG_SND_SUPPORT_OLD_API
@@ -2807,23 +2840,34 @@ static int snd_pcm_common_ioctl1(struct file *file,
2807 case SNDRV_PCM_IOCTL_DROP: 2840 case SNDRV_PCM_IOCTL_DROP:
2808 return snd_pcm_drop(substream); 2841 return snd_pcm_drop(substream);
2809 case SNDRV_PCM_IOCTL_PAUSE: 2842 case SNDRV_PCM_IOCTL_PAUSE:
2810 { 2843 return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
2811 int res; 2844 substream,
2812 snd_pcm_stream_lock_irq(substream); 2845 (int)(unsigned long)arg);
2813 res = snd_pcm_pause(substream, (int)(unsigned long)arg);
2814 snd_pcm_stream_unlock_irq(substream);
2815 return res;
2816 }
2817 } 2846 }
2818 pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); 2847 pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
2819 return -ENOTTY; 2848 return -ENOTTY;
2820} 2849}
2821 2850
2851static int snd_pcm_common_ioctl1(struct file *file,
2852 struct snd_pcm_substream *substream,
2853 unsigned int cmd, void __user *arg)
2854{
2855 struct snd_card *card = substream->pcm->card;
2856 int res;
2857
2858 snd_power_lock(card);
2859 res = snd_power_wait(card, SNDRV_CTL_POWER_D0);
2860 if (res >= 0)
2861 res = snd_pcm_common_ioctl(file, substream, cmd, arg);
2862 snd_power_unlock(card);
2863 return res;
2864}
2865
2822static int snd_pcm_playback_ioctl1(struct file *file, 2866static int snd_pcm_playback_ioctl1(struct file *file,
2823 struct snd_pcm_substream *substream, 2867 struct snd_pcm_substream *substream,
2824 unsigned int cmd, void __user *arg) 2868 unsigned int cmd, void __user *arg)
2825{ 2869{
2826 if (snd_BUG_ON(!substream)) 2870 if (PCM_RUNTIME_CHECK(substream))
2827 return -ENXIO; 2871 return -ENXIO;
2828 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) 2872 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
2829 return -EINVAL; 2873 return -EINVAL;
@@ -2903,7 +2947,7 @@ static int snd_pcm_capture_ioctl1(struct file *file,
2903 struct snd_pcm_substream *substream, 2947 struct snd_pcm_substream *substream,
2904 unsigned int cmd, void __user *arg) 2948 unsigned int cmd, void __user *arg)
2905{ 2949{
2906 if (snd_BUG_ON(!substream)) 2950 if (PCM_RUNTIME_CHECK(substream))
2907 return -ENXIO; 2951 return -ENXIO;
2908 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) 2952 if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
2909 return -EINVAL; 2953 return -EINVAL;
@@ -3007,30 +3051,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
3007 (void __user *)arg); 3051 (void __user *)arg);
3008} 3052}
3009 3053
3054/**
3055 * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
3056 * @substream: PCM substream
3057 * @cmd: IOCTL cmd
3058 * @arg: IOCTL argument
3059 *
3060 * The function is provided primarily for OSS layer and USB gadget drivers,
3061 * and it allows only the limited set of ioctls (hw_params, sw_params,
3062 * prepare, start, drain, drop, forward).
3063 */
3010int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, 3064int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
3011 unsigned int cmd, void *arg) 3065 unsigned int cmd, void *arg)
3012{ 3066{
3013 mm_segment_t fs; 3067 snd_pcm_uframes_t *frames = arg;
3014 int result; 3068 snd_pcm_sframes_t result;
3015 3069
3016 fs = snd_enter_user(); 3070 switch (cmd) {
3017 switch (substream->stream) { 3071 case SNDRV_PCM_IOCTL_FORWARD:
3018 case SNDRV_PCM_STREAM_PLAYBACK: 3072 {
3019 result = snd_pcm_playback_ioctl1(NULL, substream, cmd, 3073 /* provided only for OSS; capture-only and no value returned */
3020 (void __user *)arg); 3074 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
3021 break; 3075 return -EINVAL;
3022 case SNDRV_PCM_STREAM_CAPTURE: 3076 result = snd_pcm_capture_forward(substream, *frames);
3023 result = snd_pcm_capture_ioctl1(NULL, substream, cmd, 3077 return result < 0 ? result : 0;
3024 (void __user *)arg); 3078 }
3025 break; 3079 case SNDRV_PCM_IOCTL_HW_PARAMS:
3080 return snd_pcm_hw_params(substream, arg);
3081 case SNDRV_PCM_IOCTL_SW_PARAMS:
3082 return snd_pcm_sw_params(substream, arg);
3083 case SNDRV_PCM_IOCTL_PREPARE:
3084 return snd_pcm_prepare(substream, NULL);
3085 case SNDRV_PCM_IOCTL_START:
3086 return snd_pcm_start_lock_irq(substream);
3087 case SNDRV_PCM_IOCTL_DRAIN:
3088 return snd_pcm_drain(substream, NULL);
3089 case SNDRV_PCM_IOCTL_DROP:
3090 return snd_pcm_drop(substream);
3091 case SNDRV_PCM_IOCTL_DELAY:
3092 {
3093 result = snd_pcm_delay(substream);
3094 if (result < 0)
3095 return result;
3096 *frames = result;
3097 return 0;
3098 }
3026 default: 3099 default:
3027 result = -EINVAL; 3100 return -EINVAL;
3028 break;
3029 } 3101 }
3030 snd_leave_user(fs);
3031 return result;
3032} 3102}
3033
3034EXPORT_SYMBOL(snd_pcm_kernel_ioctl); 3103EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
3035 3104
3036static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, 3105static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
@@ -3314,10 +3383,41 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
3314 area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; 3383 area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3315 return 0; 3384 return 0;
3316} 3385}
3386
3387static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
3388{
3389 if (pcm_file->no_compat_mmap)
3390 return false;
3391 /* See pcm_control_mmap_allowed() below.
3392 * Since older alsa-lib requires both status and control mmaps to be
3393 * coupled, we have to disable the status mmap for old alsa-lib, too.
3394 */
3395 if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
3396 (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
3397 return false;
3398 return true;
3399}
3400
3401static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
3402{
3403 if (pcm_file->no_compat_mmap)
3404 return false;
3405 /* Disallow the control mmap when SYNC_APPLPTR flag is set;
3406 * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
3407 * thus it effectively assures the manual update of appl_ptr.
3408 */
3409 if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
3410 return false;
3411 return true;
3412}
3413
3317#else /* ! coherent mmap */ 3414#else /* ! coherent mmap */
3318/* 3415/*
3319 * don't support mmap for status and control records. 3416 * don't support mmap for status and control records.
3320 */ 3417 */
3418#define pcm_status_mmap_allowed(pcm_file) false
3419#define pcm_control_mmap_allowed(pcm_file) false
3420
3321static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, 3421static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
3322 struct vm_area_struct *area) 3422 struct vm_area_struct *area)
3323{ 3423{
@@ -3437,7 +3537,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3437 area->vm_page_prot = pgprot_noncached(area->vm_page_prot); 3537 area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
3438 return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); 3538 return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
3439} 3539}
3440
3441EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); 3540EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
3442#endif /* SNDRV_PCM_INFO_MMAP */ 3541#endif /* SNDRV_PCM_INFO_MMAP */
3443 3542
@@ -3486,7 +3585,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3486 atomic_inc(&substream->mmap_count); 3585 atomic_inc(&substream->mmap_count);
3487 return err; 3586 return err;
3488} 3587}
3489
3490EXPORT_SYMBOL(snd_pcm_mmap_data); 3588EXPORT_SYMBOL(snd_pcm_mmap_data);
3491 3589
3492static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) 3590static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
@@ -3503,11 +3601,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
3503 offset = area->vm_pgoff << PAGE_SHIFT; 3601 offset = area->vm_pgoff << PAGE_SHIFT;
3504 switch (offset) { 3602 switch (offset) {
3505 case SNDRV_PCM_MMAP_OFFSET_STATUS: 3603 case SNDRV_PCM_MMAP_OFFSET_STATUS:
3506 if (pcm_file->no_compat_mmap) 3604 if (!pcm_status_mmap_allowed(pcm_file))
3507 return -ENXIO; 3605 return -ENXIO;
3508 return snd_pcm_mmap_status(substream, file, area); 3606 return snd_pcm_mmap_status(substream, file, area);
3509 case SNDRV_PCM_MMAP_OFFSET_CONTROL: 3607 case SNDRV_PCM_MMAP_OFFSET_CONTROL:
3510 if (pcm_file->no_compat_mmap) 3608 if (!pcm_control_mmap_allowed(pcm_file))
3511 return -ENXIO; 3609 return -ENXIO;
3512 return snd_pcm_mmap_control(substream, file, area); 3610 return snd_pcm_mmap_control(substream, file, area);
3513 default: 3611 default:
@@ -3603,12 +3701,17 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
3603 } 3701 }
3604 snd_pcm_hw_convert_from_old_params(params, oparams); 3702 snd_pcm_hw_convert_from_old_params(params, oparams);
3605 err = snd_pcm_hw_refine(substream, params); 3703 err = snd_pcm_hw_refine(substream, params);
3606 snd_pcm_hw_convert_to_old_params(oparams, params); 3704 if (err < 0)
3607 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { 3705 goto out_old;
3608 if (!err)
3609 err = -EFAULT;
3610 }
3611 3706
3707 err = fixup_unreferenced_params(substream, params);
3708 if (err < 0)
3709 goto out_old;
3710
3711 snd_pcm_hw_convert_to_old_params(oparams, params);
3712 if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3713 err = -EFAULT;
3714out_old:
3612 kfree(oparams); 3715 kfree(oparams);
3613out: 3716out:
3614 kfree(params); 3717 kfree(params);
@@ -3631,14 +3734,16 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
3631 err = PTR_ERR(oparams); 3734 err = PTR_ERR(oparams);
3632 goto out; 3735 goto out;
3633 } 3736 }
3737
3634 snd_pcm_hw_convert_from_old_params(params, oparams); 3738 snd_pcm_hw_convert_from_old_params(params, oparams);
3635 err = snd_pcm_hw_params(substream, params); 3739 err = snd_pcm_hw_params(substream, params);
3636 snd_pcm_hw_convert_to_old_params(oparams, params); 3740 if (err < 0)
3637 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { 3741 goto out_old;
3638 if (!err)
3639 err = -EFAULT;
3640 }
3641 3742
3743 snd_pcm_hw_convert_to_old_params(oparams, params);
3744 if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3745 err = -EFAULT;
3746out_old:
3642 kfree(oparams); 3747 kfree(oparams);
3643out: 3748out:
3644 kfree(params); 3749 kfree(params);