aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/compress_offload.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index bea523a5d852..3eb47d0006a7 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -123,6 +123,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
123 } 123 }
124 runtime->state = SNDRV_PCM_STATE_OPEN; 124 runtime->state = SNDRV_PCM_STATE_OPEN;
125 init_waitqueue_head(&runtime->sleep); 125 init_waitqueue_head(&runtime->sleep);
126 init_waitqueue_head(&runtime->wait);
126 data->stream.runtime = runtime; 127 data->stream.runtime = runtime;
127 f->private_data = (void *)data; 128 f->private_data = (void *)data;
128 mutex_lock(&compr->lock); 129 mutex_lock(&compr->lock);
@@ -682,12 +683,34 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
682 if (!retval) { 683 if (!retval) {
683 stream->runtime->state = SNDRV_PCM_STATE_SETUP; 684 stream->runtime->state = SNDRV_PCM_STATE_SETUP;
684 wake_up(&stream->runtime->sleep); 685 wake_up(&stream->runtime->sleep);
686 snd_compr_drain_notify(stream);
685 stream->runtime->total_bytes_available = 0; 687 stream->runtime->total_bytes_available = 0;
686 stream->runtime->total_bytes_transferred = 0; 688 stream->runtime->total_bytes_transferred = 0;
687 } 689 }
688 return retval; 690 return retval;
689} 691}
690 692
693static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
694{
695 /*
696 * We are called with lock held. So drop the lock while we wait for
697 * drain complete notfication from the driver
698 *
699 * It is expected that driver will notify the drain completion and then
700 * stream will be moved to SETUP state, even if draining resulted in an
701 * error. We can trigger next track after this.
702 */
703 stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
704 mutex_unlock(&stream->device->lock);
705
706 wait_event(stream->runtime->wait, stream->runtime->drain_wake);
707
708 wake_up(&stream->runtime->sleep);
709 mutex_lock(&stream->device->lock);
710
711 return 0;
712}
713
691static int snd_compr_drain(struct snd_compr_stream *stream) 714static int snd_compr_drain(struct snd_compr_stream *stream)
692{ 715{
693 int retval; 716 int retval;
@@ -695,11 +718,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream)
695 if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || 718 if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
696 stream->runtime->state == SNDRV_PCM_STATE_SETUP) 719 stream->runtime->state == SNDRV_PCM_STATE_SETUP)
697 return -EPERM; 720 return -EPERM;
721
722 stream->runtime->drain_wake = 0;
698 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); 723 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
699 if (!retval) { 724 if (retval) {
700 stream->runtime->state = SNDRV_PCM_STATE_DRAINING; 725 pr_err("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
701 wake_up(&stream->runtime->sleep); 726 wake_up(&stream->runtime->sleep);
727 return retval;
702 } 728 }
729
730 retval = snd_compress_wait_for_drain(stream);
731 stream->runtime->state = SNDRV_PCM_STATE_SETUP;
703 return retval; 732 return retval;
704} 733}
705 734
@@ -735,10 +764,16 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream)
735 if (stream->next_track == false) 764 if (stream->next_track == false)
736 return -EPERM; 765 return -EPERM;
737 766
767 stream->runtime->drain_wake = 0;
738 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); 768 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
769 if (retval) {
770 pr_err("Partial drain returned failure\n");
771 wake_up(&stream->runtime->sleep);
772 return retval;
773 }
739 774
740 stream->next_track = false; 775 stream->next_track = false;
741 return retval; 776 return snd_compress_wait_for_drain(stream);
742} 777}
743 778
744static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 779static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)