diff options
Diffstat (limited to '')
-rw-r--r-- | sound/core/compress_offload.c | 168 |
1 files changed, 88 insertions, 80 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 9de1c9a0173e..243acad89fd3 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -47,8 +47,6 @@ * driver should be able to register multiple nodes */ -static DEFINE_MUTEX(device_mutex); - struct snd_compr_file { unsigned long caps; struct snd_compr_stream stream; @@ -488,6 +486,49 @@ out: } #endif /* !COMPR_CODEC_CAPS_OVERFLOW */ +int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size) +{ + struct snd_dma_buffer *dmab; + int ret; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); + if (!dmab) + return -ENOMEM; + dmab->dev = stream->dma_buffer.dev; + ret = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, size, dmab); + if (ret < 0) { + kfree(dmab); + return ret; + } + + snd_compr_set_runtime_buffer(stream, dmab); + stream->runtime->dma_bytes = size; + return 1; +} +EXPORT_SYMBOL(snd_compr_malloc_pages); + +int snd_compr_free_pages(struct snd_compr_stream *stream) +{ + struct snd_compr_runtime *runtime; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + runtime = stream->runtime; + if (runtime->dma_area == NULL) + return 0; + if (runtime->dma_buffer_p != &stream->dma_buffer) { + /* It's a newly allocated buffer. Release it now. */ + snd_dma_free_pages(runtime->dma_buffer_p); + kfree(runtime->dma_buffer_p); + } + + snd_compr_set_runtime_buffer(stream, NULL); + return 0; +} +EXPORT_SYMBOL(snd_compr_free_pages); + /* revisit this with snd_pcm_preallocate_xxx */ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, struct snd_compr_params *params) @@ -666,11 +707,22 @@ static int snd_compr_pause(struct snd_compr_stream *stream) { int retval; - if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) + switch (stream->runtime->state) { + case SNDRV_PCM_STATE_RUNNING: + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + break; + case SNDRV_PCM_STATE_DRAINING: + if (!stream->device->use_pause_in_draining) + return -EPERM; + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval) + stream->pause_in_draining = true; + break; + default: return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + } return retval; } @@ -678,11 +730,22 @@ static int snd_compr_resume(struct snd_compr_stream *stream) { int retval; - if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) + switch (stream->runtime->state) { + case SNDRV_PCM_STATE_PAUSED: + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + break; + case SNDRV_PCM_STATE_DRAINING: + if (!stream->pause_in_draining) + return -EPERM; + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); + if (!retval) + stream->pause_in_draining = false; + break; + default: return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + } return retval; } @@ -722,6 +785,10 @@ static int snd_compr_stop(struct snd_compr_stream *stream) retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { + /* clear flags and stop any drain wait */ + stream->partial_drain = false; + stream->metadata_set = false; + stream->pause_in_draining = false; snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; @@ -743,7 +810,7 @@ static void error_delayed_work(struct work_struct *work) mutex_unlock(&stream->device->lock); } -/* +/** * snd_compr_stop_error: Report a fatal error on a stream * @stream: pointer to stream * @state: state to transition the stream to @@ -751,6 +818,8 @@ static void error_delayed_work(struct work_struct *work) * Stop the stream and set its state. * * Should be called with compressed device lock held. + * + * Return: zero if successful, or a negative error code */ int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state) @@ -879,6 +948,7 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; + stream->partial_drain = true; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); if (retval) { pr_debug("Partial drain returned failure\n"); @@ -985,7 +1055,7 @@ static const struct file_operations snd_compr_file_ops = { static int snd_compress_dev_register(struct snd_device *device) { - int ret = -EINVAL; + int ret; struct snd_compr *compr; if (snd_BUG_ON(!device || !device->device_data)) @@ -1062,7 +1132,7 @@ static void snd_compress_proc_done(struct snd_compr *compr) static inline void snd_compress_set_id(struct snd_compr *compr, const char *id) { - strlcpy(compr->id, id, sizeof(compr->id)); + strscpy(compr->id, id, sizeof(compr->id)); } #else static inline int snd_compress_proc_init(struct snd_compr *compr) @@ -1089,12 +1159,15 @@ static int snd_compress_dev_free(struct snd_device *device) return 0; } -/* +/** * snd_compress_new: create new compress device * @card: sound card pointer * @device: device number * @dirn: device direction, should be of type enum snd_compr_direction + * @id: ID string * @compr: compress device pointer + * + * Return: zero if successful, or a negative error code */ int snd_compress_new(struct snd_card *card, int device, int dirn, const char *id, struct snd_compr *compr) @@ -1109,6 +1182,7 @@ int snd_compress_new(struct snd_card *card, int device, compr->card = card; compr->device = device; compr->direction = dirn; + mutex_init(&compr->lock); snd_compress_set_id(compr, id); @@ -1123,72 +1197,6 @@ int snd_compress_new(struct snd_card *card, int device, } EXPORT_SYMBOL_GPL(snd_compress_new); -static int snd_compress_add_device(struct snd_compr *device) -{ - int ret; - - if (!device->card) - return -EINVAL; - - /* register the card */ - ret = snd_card_register(device->card); - if (ret) - goto out; - return 0; - -out: - pr_err("failed with %d\n", ret); - return ret; - -} - -static int snd_compress_remove_device(struct snd_compr *device) -{ - return snd_card_free(device->card); -} - -/** - * snd_compress_register - register compressed device - * - * @device: compressed device to register - */ -int snd_compress_register(struct snd_compr *device) -{ - int retval; - - if (device->name == NULL || device->ops == NULL) - return -EINVAL; - - pr_debug("Registering compressed device %s\n", device->name); - if (snd_BUG_ON(!device->ops->open)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->free)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->set_params)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->trigger)) - return -EINVAL; - - mutex_init(&device->lock); - - /* register a compressed card */ - mutex_lock(&device_mutex); - retval = snd_compress_add_device(device); - mutex_unlock(&device_mutex); - return retval; -} -EXPORT_SYMBOL_GPL(snd_compress_register); - -int snd_compress_deregister(struct snd_compr *device) -{ - pr_debug("Removing compressed device %s\n", device->name); - mutex_lock(&device_mutex); - snd_compress_remove_device(device); - mutex_unlock(&device_mutex); - return 0; -} -EXPORT_SYMBOL_GPL(snd_compress_deregister); - MODULE_DESCRIPTION("ALSA Compressed offload framework"); MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>"); MODULE_LICENSE("GPL v2"); |