Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ALSA] usb-audio: allow pausing

Add pause capabilities for both USB playback and capture streams.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>

authored by

Clemens Ladisch and committed by
Jaroslav Kysela
e4f8e656 1700f308

+31 -9
+31 -9
sound/usb/usbaudio.c
··· 391 391 return 0; 392 392 } 393 393 394 + /* 395 + * Process after capture complete when paused. Nothing to do. 396 + */ 397 + static int retire_paused_capture_urb(struct snd_usb_substream *subs, 398 + struct snd_pcm_runtime *runtime, 399 + struct urb *urb) 400 + { 401 + return 0; 402 + } 403 + 394 404 395 405 /* 396 406 * prepare urb for full speed playback sync pipe ··· 503 493 } 504 494 505 495 /* 506 - * Prepare urb for streaming before playback starts. 496 + * Prepare urb for streaming before playback starts or when paused. 507 497 * 508 - * We don't yet have data, so we send a frame of silence. 498 + * We don't have any data, so we send a frame of silence. 509 499 */ 510 - static int prepare_startup_playback_urb(struct snd_usb_substream *subs, 511 - struct snd_pcm_runtime *runtime, 512 - struct urb *urb) 500 + static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, 501 + struct snd_pcm_runtime *runtime, 502 + struct urb *urb) 513 503 { 514 504 unsigned int i, offs, counts; 515 505 struct snd_urb_ctx *ctx = urb->context; ··· 632 622 */ 633 623 static struct snd_urb_ops audio_urb_ops[2] = { 634 624 { 635 - .prepare = prepare_startup_playback_urb, 625 + .prepare = prepare_nodata_playback_urb, 636 626 .retire = retire_playback_urb, 637 627 .prepare_sync = prepare_playback_sync_urb, 638 628 .retire_sync = retire_playback_sync_urb, ··· 647 637 648 638 static struct snd_urb_ops audio_urb_ops_high_speed[2] = { 649 639 { 650 - .prepare = prepare_startup_playback_urb, 640 + .prepare = prepare_nodata_playback_urb, 651 641 .retire = retire_playback_urb, 652 642 .prepare_sync = prepare_playback_sync_urb_hs, 653 643 .retire_sync = retire_playback_sync_urb_hs, ··· 935 925 936 926 switch (cmd) { 937 927 case SNDRV_PCM_TRIGGER_START: 928 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 938 929 subs->ops.prepare = prepare_playback_urb; 939 930 return 0; 940 931 case SNDRV_PCM_TRIGGER_STOP: 941 932 return deactivate_urbs(subs, 0, 0); 933 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 934 + subs->ops.prepare = prepare_nodata_playback_urb; 935 + return 0; 942 936 default: 943 937 return -EINVAL; 944 938 } ··· 958 944 959 945 switch (cmd) { 960 946 case SNDRV_PCM_TRIGGER_START: 947 + subs->ops.retire = retire_capture_urb; 961 948 return start_urbs(subs, substream->runtime); 962 949 case SNDRV_PCM_TRIGGER_STOP: 963 950 return deactivate_urbs(subs, 0, 0); 951 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 952 + subs->ops.retire = retire_paused_capture_urb; 953 + return 0; 954 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 955 + subs->ops.retire = retire_capture_urb; 956 + return 0; 964 957 default: 965 958 return -EINVAL; 966 959 } ··· 1526 1505 /* for playback, submit the URBs now; otherwise, the first hwptr_done 1527 1506 * updates for all URBs would happen at the same time when starting */ 1528 1507 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { 1529 - subs->ops.prepare = prepare_startup_playback_urb; 1508 + subs->ops.prepare = prepare_nodata_playback_urb; 1530 1509 return start_urbs(subs, runtime); 1531 1510 } else 1532 1511 return 0; ··· 1538 1517 SNDRV_PCM_INFO_MMAP_VALID | 1539 1518 SNDRV_PCM_INFO_BATCH | 1540 1519 SNDRV_PCM_INFO_INTERLEAVED | 1541 - SNDRV_PCM_INFO_BLOCK_TRANSFER, 1520 + SNDRV_PCM_INFO_BLOCK_TRANSFER | 1521 + SNDRV_PCM_INFO_PAUSE, 1542 1522 .buffer_bytes_max = 1024 * 1024, 1543 1523 .period_bytes_min = 64, 1544 1524 .period_bytes_max = 512 * 1024,