ALSA: compress: allow writes in SNDRV_PCM_STATE_PREPARED state
[linux-2.6-block.git] / sound / core / compress_offload.c
CommitLineData
b21c60a4
VK
1/*
2 * compress_core.c - compress offload core
3 *
4 * Copyright (C) 2011 Intel Corporation
5 * Authors: Vinod Koul <vinod.koul@linux.intel.com>
6 * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 */
25#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
26#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
27
28#include <linux/file.h>
29#include <linux/fs.h>
30#include <linux/list.h>
f0283b58 31#include <linux/math64.h>
b21c60a4
VK
32#include <linux/mm.h>
33#include <linux/mutex.h>
34#include <linux/poll.h>
35#include <linux/slab.h>
36#include <linux/sched.h>
f0283b58 37#include <linux/types.h>
b21c60a4
VK
38#include <linux/uio.h>
39#include <linux/uaccess.h>
40#include <linux/module.h>
c1036889 41#include <linux/compat.h>
b21c60a4
VK
42#include <sound/core.h>
43#include <sound/initval.h>
31742724 44#include <sound/info.h>
b21c60a4
VK
45#include <sound/compress_params.h>
46#include <sound/compress_offload.h>
47#include <sound/compress_driver.h>
48
462b3f16
TI
49/* struct snd_compr_codec_caps overflows the ioctl bit size for some
50 * architectures, so we need to disable the relevant ioctls.
51 */
52#if _IOC_SIZEBITS < 14
53#define COMPR_CODEC_CAPS_OVERFLOW
54#endif
55
b21c60a4
VK
56/* TODO:
57 * - add substream support for multiple devices in case of
58 * SND_DYNAMIC_MINORS is not used
59 * - Multiple node representation
60 * driver should be able to register multiple nodes
61 */
62
63static DEFINE_MUTEX(device_mutex);
64
65struct snd_compr_file {
66 unsigned long caps;
67 struct snd_compr_stream stream;
68};
69
70/*
71 * a note on stream states used:
72 * we use follwing states in the compressed core
73 * SNDRV_PCM_STATE_OPEN: When stream has been opened.
74 * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by
75 * calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this
76 * state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain.
77 * SNDRV_PCM_STATE_RUNNING: When stream has been started and is
78 * decoding/encoding and rendering/capturing data.
79 * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done
80 * by calling SNDRV_COMPRESS_DRAIN.
81 * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling
82 * SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling
83 * SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively.
84 */
85static int snd_compr_open(struct inode *inode, struct file *f)
86{
87 struct snd_compr *compr;
88 struct snd_compr_file *data;
89 struct snd_compr_runtime *runtime;
90 enum snd_compr_direction dirn;
91 int maj = imajor(inode);
92 int ret;
93
81cb3246 94 if ((f->f_flags & O_ACCMODE) == O_WRONLY)
b21c60a4 95 dirn = SND_COMPRESS_PLAYBACK;
81cb3246 96 else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
b21c60a4 97 dirn = SND_COMPRESS_CAPTURE;
81cb3246 98 else
b21c60a4 99 return -EINVAL;
b21c60a4
VK
100
101 if (maj == snd_major)
102 compr = snd_lookup_minor_data(iminor(inode),
103 SNDRV_DEVICE_TYPE_COMPRESS);
104 else
105 return -EBADFD;
106
107 if (compr == NULL) {
108 pr_err("no device data!!!\n");
109 return -ENODEV;
110 }
111
112 if (dirn != compr->direction) {
113 pr_err("this device doesn't support this direction\n");
a0830dbd 114 snd_card_unref(compr->card);
b21c60a4
VK
115 return -EINVAL;
116 }
117
118 data = kzalloc(sizeof(*data), GFP_KERNEL);
a0830dbd
TI
119 if (!data) {
120 snd_card_unref(compr->card);
b21c60a4 121 return -ENOMEM;
a0830dbd 122 }
b21c60a4
VK
123 data->stream.ops = compr->ops;
124 data->stream.direction = dirn;
125 data->stream.private_data = compr->private_data;
126 data->stream.device = compr;
127 runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
128 if (!runtime) {
129 kfree(data);
a0830dbd 130 snd_card_unref(compr->card);
b21c60a4
VK
131 return -ENOMEM;
132 }
133 runtime->state = SNDRV_PCM_STATE_OPEN;
134 init_waitqueue_head(&runtime->sleep);
135 data->stream.runtime = runtime;
136 f->private_data = (void *)data;
137 mutex_lock(&compr->lock);
138 ret = compr->ops->open(&data->stream);
139 mutex_unlock(&compr->lock);
140 if (ret) {
141 kfree(runtime);
142 kfree(data);
143 }
a0830dbd 144 snd_card_unref(compr->card);
749d3223 145 return ret;
b21c60a4
VK
146}
147
148static int snd_compr_free(struct inode *inode, struct file *f)
149{
150 struct snd_compr_file *data = f->private_data;
b26d19e4
LG
151 struct snd_compr_runtime *runtime = data->stream.runtime;
152
153 switch (runtime->state) {
154 case SNDRV_PCM_STATE_RUNNING:
155 case SNDRV_PCM_STATE_DRAINING:
156 case SNDRV_PCM_STATE_PAUSED:
157 data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
158 break;
159 default:
160 break;
161 }
162
b21c60a4
VK
163 data->stream.ops->free(&data->stream);
164 kfree(data->stream.runtime->buffer);
165 kfree(data->stream.runtime);
166 kfree(data);
167 return 0;
168}
169
17ac8e5c 170static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
b21c60a4
VK
171 struct snd_compr_tstamp *tstamp)
172{
173 if (!stream->ops->pointer)
17ac8e5c 174 return -ENOTSUPP;
b21c60a4
VK
175 stream->ops->pointer(stream, tstamp);
176 pr_debug("dsp consumed till %d total %d bytes\n",
177 tstamp->byte_offset, tstamp->copied_total);
5b1f79f7
CK
178 if (stream->direction == SND_COMPRESS_PLAYBACK)
179 stream->runtime->total_bytes_transferred = tstamp->copied_total;
180 else
181 stream->runtime->total_bytes_available = tstamp->copied_total;
17ac8e5c 182 return 0;
b21c60a4
VK
183}
184
185static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
186 struct snd_compr_avail *avail)
187{
17ac8e5c 188 memset(avail, 0, sizeof(*avail));
b21c60a4 189 snd_compr_update_tstamp(stream, &avail->tstamp);
17ac8e5c 190 /* Still need to return avail even if tstamp can't be filled in */
b21c60a4 191
b21c60a4 192 if (stream->runtime->total_bytes_available == 0 &&
5b1f79f7
CK
193 stream->runtime->state == SNDRV_PCM_STATE_SETUP &&
194 stream->direction == SND_COMPRESS_PLAYBACK) {
b21c60a4
VK
195 pr_debug("detected init and someone forgot to do a write\n");
196 return stream->runtime->buffer_size;
197 }
198 pr_debug("app wrote %lld, DSP consumed %lld\n",
199 stream->runtime->total_bytes_available,
200 stream->runtime->total_bytes_transferred);
201 if (stream->runtime->total_bytes_available ==
202 stream->runtime->total_bytes_transferred) {
5b1f79f7
CK
203 if (stream->direction == SND_COMPRESS_PLAYBACK) {
204 pr_debug("both pointers are same, returning full avail\n");
205 return stream->runtime->buffer_size;
206 } else {
207 pr_debug("both pointers are same, returning no avail\n");
208 return 0;
209 }
b21c60a4
VK
210 }
211
5b1f79f7
CK
212 avail->avail = stream->runtime->total_bytes_available -
213 stream->runtime->total_bytes_transferred;
214 if (stream->direction == SND_COMPRESS_PLAYBACK)
215 avail->avail = stream->runtime->buffer_size - avail->avail;
216
4c28e32d
CK
217 pr_debug("ret avail as %lld\n", avail->avail);
218 return avail->avail;
b21c60a4
VK
219}
220
221static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
222{
223 struct snd_compr_avail avail;
224
225 return snd_compr_calc_avail(stream, &avail);
226}
227
228static int
229snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
230{
231 struct snd_compr_avail ioctl_avail;
232 size_t avail;
233
234 avail = snd_compr_calc_avail(stream, &ioctl_avail);
235 ioctl_avail.avail = avail;
236
237 if (copy_to_user((__u64 __user *)arg,
238 &ioctl_avail, sizeof(ioctl_avail)))
239 return -EFAULT;
240 return 0;
241}
242
243static int snd_compr_write_data(struct snd_compr_stream *stream,
244 const char __user *buf, size_t count)
245{
246 void *dstn;
247 size_t copy;
248 struct snd_compr_runtime *runtime = stream->runtime;
f0283b58
CK
249 /* 64-bit Modulus */
250 u64 app_pointer = div64_u64(runtime->total_bytes_available,
251 runtime->buffer_size);
252 app_pointer = runtime->total_bytes_available -
253 (app_pointer * runtime->buffer_size);
b21c60a4 254
f0283b58 255 dstn = runtime->buffer + app_pointer;
b21c60a4 256 pr_debug("copying %ld at %lld\n",
f0283b58
CK
257 (unsigned long)count, app_pointer);
258 if (count < runtime->buffer_size - app_pointer) {
b21c60a4
VK
259 if (copy_from_user(dstn, buf, count))
260 return -EFAULT;
b21c60a4 261 } else {
f0283b58 262 copy = runtime->buffer_size - app_pointer;
b21c60a4
VK
263 if (copy_from_user(dstn, buf, copy))
264 return -EFAULT;
265 if (copy_from_user(runtime->buffer, buf + copy, count - copy))
266 return -EFAULT;
b21c60a4
VK
267 }
268 /* if DSP cares, let it know data has been written */
269 if (stream->ops->ack)
270 stream->ops->ack(stream, count);
271 return count;
272}
273
274static ssize_t snd_compr_write(struct file *f, const char __user *buf,
275 size_t count, loff_t *offset)
276{
277 struct snd_compr_file *data = f->private_data;
278 struct snd_compr_stream *stream;
279 size_t avail;
280 int retval;
281
282 if (snd_BUG_ON(!data))
283 return -EFAULT;
284
285 stream = &data->stream;
286 mutex_lock(&stream->device->lock);
287 /* write is allowed when stream is running or has been steup */
288 if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
35383a24 289 stream->runtime->state != SNDRV_PCM_STATE_PREPARED &&
b21c60a4
VK
290 stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
291 mutex_unlock(&stream->device->lock);
292 return -EBADFD;
293 }
294
295 avail = snd_compr_get_avail(stream);
296 pr_debug("avail returned %ld\n", (unsigned long)avail);
297 /* calculate how much we can write to buffer */
298 if (avail > count)
299 avail = count;
300
4daf891c
CK
301 if (stream->ops->copy) {
302 char __user* cbuf = (char __user*)buf;
303 retval = stream->ops->copy(stream, cbuf, avail);
304 } else {
b21c60a4 305 retval = snd_compr_write_data(stream, buf, avail);
4daf891c 306 }
b21c60a4
VK
307 if (retval > 0)
308 stream->runtime->total_bytes_available += retval;
309
310 /* while initiating the stream, write should be called before START
311 * call, so in setup move state */
312 if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
313 stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
314 pr_debug("stream prepared, Houston we are good to go\n");
315 }
316
317 mutex_unlock(&stream->device->lock);
318 return retval;
319}
320
321
322static ssize_t snd_compr_read(struct file *f, char __user *buf,
323 size_t count, loff_t *offset)
324{
49bb6402
CK
325 struct snd_compr_file *data = f->private_data;
326 struct snd_compr_stream *stream;
327 size_t avail;
328 int retval;
329
330 if (snd_BUG_ON(!data))
331 return -EFAULT;
332
333 stream = &data->stream;
334 mutex_lock(&stream->device->lock);
335
75481347
VK
336 /* read is allowed when stream is running, paused, draining and setup
337 * (yes setup is state which we transition to after stop, so if user
338 * wants to read data after stop we allow that)
339 */
340 switch (stream->runtime->state) {
341 case SNDRV_PCM_STATE_OPEN:
342 case SNDRV_PCM_STATE_PREPARED:
343 case SNDRV_PCM_STATE_XRUN:
344 case SNDRV_PCM_STATE_SUSPENDED:
345 case SNDRV_PCM_STATE_DISCONNECTED:
49bb6402
CK
346 retval = -EBADFD;
347 goto out;
348 }
349
350 avail = snd_compr_get_avail(stream);
351 pr_debug("avail returned %ld\n", (unsigned long)avail);
352 /* calculate how much we can read from buffer */
353 if (avail > count)
354 avail = count;
355
356 if (stream->ops->copy) {
357 retval = stream->ops->copy(stream, buf, avail);
358 } else {
359 retval = -ENXIO;
360 goto out;
361 }
362 if (retval > 0)
363 stream->runtime->total_bytes_transferred += retval;
364
365out:
366 mutex_unlock(&stream->device->lock);
367 return retval;
b21c60a4
VK
368}
369
370static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
371{
372 return -ENXIO;
373}
374
375static inline int snd_compr_get_poll(struct snd_compr_stream *stream)
376{
377 if (stream->direction == SND_COMPRESS_PLAYBACK)
378 return POLLOUT | POLLWRNORM;
379 else
380 return POLLIN | POLLRDNORM;
381}
382
383static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
384{
385 struct snd_compr_file *data = f->private_data;
386 struct snd_compr_stream *stream;
387 size_t avail;
388 int retval = 0;
389
390 if (snd_BUG_ON(!data))
391 return -EFAULT;
392 stream = &data->stream;
393 if (snd_BUG_ON(!stream))
394 return -EFAULT;
395
396 mutex_lock(&stream->device->lock);
c15b149a 397 if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
b21c60a4
VK
398 retval = -EBADFD;
399 goto out;
400 }
401 poll_wait(f, &stream->runtime->sleep, wait);
402
403 avail = snd_compr_get_avail(stream);
404 pr_debug("avail is %ld\n", (unsigned long)avail);
405 /* check if we have at least one fragment to fill */
406 switch (stream->runtime->state) {
407 case SNDRV_PCM_STATE_DRAINING:
408 /* stream has been woken up after drain is complete
409 * draining done so set stream state to stopped
410 */
411 retval = snd_compr_get_poll(stream);
412 stream->runtime->state = SNDRV_PCM_STATE_SETUP;
413 break;
414 case SNDRV_PCM_STATE_RUNNING:
415 case SNDRV_PCM_STATE_PREPARED:
416 case SNDRV_PCM_STATE_PAUSED:
417 if (avail >= stream->runtime->fragment_size)
418 retval = snd_compr_get_poll(stream);
419 break;
420 default:
421 if (stream->direction == SND_COMPRESS_PLAYBACK)
422 retval = POLLOUT | POLLWRNORM | POLLERR;
423 else
424 retval = POLLIN | POLLRDNORM | POLLERR;
425 break;
426 }
427out:
428 mutex_unlock(&stream->device->lock);
429 return retval;
430}
431
432static int
433snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
434{
435 int retval;
436 struct snd_compr_caps caps;
437
438 if (!stream->ops->get_caps)
439 return -ENXIO;
440
1c62e9f2 441 memset(&caps, 0, sizeof(caps));
b21c60a4
VK
442 retval = stream->ops->get_caps(stream, &caps);
443 if (retval)
444 goto out;
445 if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
446 retval = -EFAULT;
447out:
448 return retval;
449}
450
462b3f16 451#ifndef COMPR_CODEC_CAPS_OVERFLOW
b21c60a4
VK
452static int
453snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
454{
455 int retval;
456 struct snd_compr_codec_caps *caps;
457
458 if (!stream->ops->get_codec_caps)
459 return -ENXIO;
460
47966e97 461 caps = kzalloc(sizeof(*caps), GFP_KERNEL);
b21c60a4
VK
462 if (!caps)
463 return -ENOMEM;
464
465 retval = stream->ops->get_codec_caps(stream, caps);
466 if (retval)
467 goto out;
468 if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
469 retval = -EFAULT;
470
471out:
472 kfree(caps);
473 return retval;
474}
462b3f16 475#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
b21c60a4
VK
476
477/* revisit this with snd_pcm_preallocate_xxx */
478static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
479 struct snd_compr_params *params)
480{
481 unsigned int buffer_size;
482 void *buffer;
483
484 buffer_size = params->buffer.fragment_size * params->buffer.fragments;
485 if (stream->ops->copy) {
486 buffer = NULL;
487 /* if copy is defined the driver will be required to copy
488 * the data from core
489 */
490 } else {
491 buffer = kmalloc(buffer_size, GFP_KERNEL);
492 if (!buffer)
493 return -ENOMEM;
494 }
495 stream->runtime->fragment_size = params->buffer.fragment_size;
496 stream->runtime->fragments = params->buffer.fragments;
497 stream->runtime->buffer = buffer;
498 stream->runtime->buffer_size = buffer_size;
499 return 0;
500}
501
4dc040a0
VK
502static int snd_compress_check_input(struct snd_compr_params *params)
503{
504 /* first let's check the buffer parameter's */
505 if (params->buffer.fragment_size == 0 ||
6217e5ed 506 params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
4dc040a0
VK
507 return -EINVAL;
508
fb4a9779
VK
509 /* now codec parameters */
510 if (params->codec.id == 0 || params->codec.id > SND_AUDIOCODEC_MAX)
511 return -EINVAL;
512
513 if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
514 return -EINVAL;
fb4a9779 515
4dc040a0
VK
516 return 0;
517}
518
b21c60a4
VK
519static int
520snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
521{
522 struct snd_compr_params *params;
523 int retval;
524
525 if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
526 /*
527 * we should allow parameter change only when stream has been
528 * opened not in other cases
529 */
530 params = kmalloc(sizeof(*params), GFP_KERNEL);
531 if (!params)
532 return -ENOMEM;
769fab2a
JJ
533 if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
534 retval = -EFAULT;
535 goto out;
536 }
4dc040a0
VK
537
538 retval = snd_compress_check_input(params);
539 if (retval)
540 goto out;
541
b21c60a4
VK
542 retval = snd_compr_allocate_buffer(stream, params);
543 if (retval) {
769fab2a
JJ
544 retval = -ENOMEM;
545 goto out;
b21c60a4 546 }
4dc040a0 547
b21c60a4
VK
548 retval = stream->ops->set_params(stream, params);
549 if (retval)
550 goto out;
49bb6402 551
9727b490
JK
552 stream->metadata_set = false;
553 stream->next_track = false;
49bb6402
CK
554
555 if (stream->direction == SND_COMPRESS_PLAYBACK)
556 stream->runtime->state = SNDRV_PCM_STATE_SETUP;
557 else
558 stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
769fab2a 559 } else {
b21c60a4 560 return -EPERM;
769fab2a 561 }
b21c60a4
VK
562out:
563 kfree(params);
564 return retval;
565}
566
567static int
568snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
569{
570 struct snd_codec *params;
571 int retval;
572
573 if (!stream->ops->get_params)
574 return -EBADFD;
575
47966e97 576 params = kzalloc(sizeof(*params), GFP_KERNEL);
b21c60a4
VK
577 if (!params)
578 return -ENOMEM;
579 retval = stream->ops->get_params(stream, params);
580 if (retval)
581 goto out;
582 if (copy_to_user((char __user *)arg, params, sizeof(*params)))
583 retval = -EFAULT;
584
585out:
586 kfree(params);
587 return retval;
588}
589
9727b490
JK
590static int
591snd_compr_get_metadata(struct snd_compr_stream *stream, unsigned long arg)
592{
593 struct snd_compr_metadata metadata;
594 int retval;
595
596 if (!stream->ops->get_metadata)
597 return -ENXIO;
598
599 if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata)))
600 return -EFAULT;
601
602 retval = stream->ops->get_metadata(stream, &metadata);
603 if (retval != 0)
604 return retval;
605
606 if (copy_to_user((void __user *)arg, &metadata, sizeof(metadata)))
607 return -EFAULT;
608
609 return 0;
610}
611
612static int
613snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
614{
615 struct snd_compr_metadata metadata;
616 int retval;
617
618 if (!stream->ops->set_metadata)
619 return -ENXIO;
620 /*
621 * we should allow parameter change only when stream has been
622 * opened not in other cases
623 */
624 if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata)))
625 return -EFAULT;
626
627 retval = stream->ops->set_metadata(stream, &metadata);
628 stream->metadata_set = true;
629
630 return retval;
631}
632
b21c60a4
VK
633static inline int
634snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
635{
17ac8e5c
RF
636 struct snd_compr_tstamp tstamp = {0};
637 int ret;
b21c60a4 638
17ac8e5c
RF
639 ret = snd_compr_update_tstamp(stream, &tstamp);
640 if (ret == 0)
641 ret = copy_to_user((struct snd_compr_tstamp __user *)arg,
642 &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
643 return ret;
b21c60a4
VK
644}
645
646static int snd_compr_pause(struct snd_compr_stream *stream)
647{
648 int retval;
649
650 if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
651 return -EPERM;
652 retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
6b18f793 653 if (!retval)
b21c60a4 654 stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
b21c60a4
VK
655 return retval;
656}
657
658static int snd_compr_resume(struct snd_compr_stream *stream)
659{
660 int retval;
661
662 if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
663 return -EPERM;
664 retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
665 if (!retval)
666 stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
667 return retval;
668}
669
670static int snd_compr_start(struct snd_compr_stream *stream)
671{
672 int retval;
673
674 if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
675 return -EPERM;
676 retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
677 if (!retval)
678 stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
679 return retval;
680}
681
682static int snd_compr_stop(struct snd_compr_stream *stream)
683{
684 int retval;
685
686 if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
687 stream->runtime->state == SNDRV_PCM_STATE_SETUP)
688 return -EPERM;
689 retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
690 if (!retval) {
917f4b5c 691 snd_compr_drain_notify(stream);
8b21460a
VK
692 stream->runtime->total_bytes_available = 0;
693 stream->runtime->total_bytes_transferred = 0;
b21c60a4
VK
694 }
695 return retval;
696}
697
917f4b5c
VK
698static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
699{
f44f2a54
VK
700 int ret;
701
917f4b5c
VK
702 /*
703 * We are called with lock held. So drop the lock while we wait for
704 * drain complete notfication from the driver
705 *
706 * It is expected that driver will notify the drain completion and then
707 * stream will be moved to SETUP state, even if draining resulted in an
708 * error. We can trigger next track after this.
709 */
710 stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
711 mutex_unlock(&stream->device->lock);
712
f44f2a54
VK
713 /* we wait for drain to complete here, drain can return when
714 * interruption occurred, wait returned error or success.
715 * For the first two cases we don't do anything different here and
716 * return after waking up
717 */
718
719 ret = wait_event_interruptible(stream->runtime->sleep,
720 (stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
721 if (ret == -ERESTARTSYS)
722 pr_debug("wait aborted by a signal");
723 else if (ret)
724 pr_debug("wait for drain failed with %d\n", ret);
725
917f4b5c
VK
726
727 wake_up(&stream->runtime->sleep);
728 mutex_lock(&stream->device->lock);
729
f44f2a54 730 return ret;
917f4b5c
VK
731}
732
b21c60a4
VK
733static int snd_compr_drain(struct snd_compr_stream *stream)
734{
735 int retval;
736
737 if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
738 stream->runtime->state == SNDRV_PCM_STATE_SETUP)
739 return -EPERM;
917f4b5c 740
b21c60a4 741 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
917f4b5c 742 if (retval) {
f44f2a54 743 pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
b21c60a4 744 wake_up(&stream->runtime->sleep);
917f4b5c 745 return retval;
b21c60a4 746 }
917f4b5c 747
f44f2a54 748 return snd_compress_wait_for_drain(stream);
b21c60a4
VK
749}
750
9727b490
JK
751static int snd_compr_next_track(struct snd_compr_stream *stream)
752{
753 int retval;
754
755 /* only a running stream can transition to next track */
756 if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
757 return -EPERM;
758
759 /* you can signal next track isf this is intended to be a gapless stream
760 * and current track metadata is set
761 */
762 if (stream->metadata_set == false)
763 return -EPERM;
764
765 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_NEXT_TRACK);
766 if (retval != 0)
767 return retval;
768 stream->metadata_set = false;
769 stream->next_track = true;
770 return 0;
771}
772
773static int snd_compr_partial_drain(struct snd_compr_stream *stream)
774{
775 int retval;
776 if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
777 stream->runtime->state == SNDRV_PCM_STATE_SETUP)
778 return -EPERM;
779 /* stream can be drained only when next track has been signalled */
780 if (stream->next_track == false)
781 return -EPERM;
782
783 retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
917f4b5c 784 if (retval) {
f44f2a54 785 pr_debug("Partial drain returned failure\n");
917f4b5c
VK
786 wake_up(&stream->runtime->sleep);
787 return retval;
788 }
9727b490
JK
789
790 stream->next_track = false;
917f4b5c 791 return snd_compress_wait_for_drain(stream);
9727b490
JK
792}
793
b21c60a4
VK
794static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
795{
796 struct snd_compr_file *data = f->private_data;
797 struct snd_compr_stream *stream;
798 int retval = -ENOTTY;
799
800 if (snd_BUG_ON(!data))
801 return -EFAULT;
802 stream = &data->stream;
803 if (snd_BUG_ON(!stream))
804 return -EFAULT;
805 mutex_lock(&stream->device->lock);
806 switch (_IOC_NR(cmd)) {
807 case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
a8d30608 808 retval = put_user(SNDRV_COMPRESS_VERSION,
b21c60a4
VK
809 (int __user *)arg) ? -EFAULT : 0;
810 break;
811 case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
812 retval = snd_compr_get_caps(stream, arg);
813 break;
462b3f16 814#ifndef COMPR_CODEC_CAPS_OVERFLOW
b21c60a4
VK
815 case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
816 retval = snd_compr_get_codec_caps(stream, arg);
817 break;
462b3f16 818#endif
b21c60a4
VK
819 case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
820 retval = snd_compr_set_params(stream, arg);
821 break;
822 case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
823 retval = snd_compr_get_params(stream, arg);
824 break;
9727b490
JK
825 case _IOC_NR(SNDRV_COMPRESS_SET_METADATA):
826 retval = snd_compr_set_metadata(stream, arg);
827 break;
828 case _IOC_NR(SNDRV_COMPRESS_GET_METADATA):
829 retval = snd_compr_get_metadata(stream, arg);
830 break;
b21c60a4
VK
831 case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
832 retval = snd_compr_tstamp(stream, arg);
833 break;
834 case _IOC_NR(SNDRV_COMPRESS_AVAIL):
835 retval = snd_compr_ioctl_avail(stream, arg);
836 break;
837 case _IOC_NR(SNDRV_COMPRESS_PAUSE):
838 retval = snd_compr_pause(stream);
839 break;
840 case _IOC_NR(SNDRV_COMPRESS_RESUME):
841 retval = snd_compr_resume(stream);
842 break;
843 case _IOC_NR(SNDRV_COMPRESS_START):
844 retval = snd_compr_start(stream);
845 break;
846 case _IOC_NR(SNDRV_COMPRESS_STOP):
847 retval = snd_compr_stop(stream);
848 break;
849 case _IOC_NR(SNDRV_COMPRESS_DRAIN):
850 retval = snd_compr_drain(stream);
851 break;
9727b490
JK
852 case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN):
853 retval = snd_compr_partial_drain(stream);
854 break;
855 case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK):
856 retval = snd_compr_next_track(stream);
857 break;
858
b21c60a4
VK
859 }
860 mutex_unlock(&stream->device->lock);
861 return retval;
862}
863
c1036889
RL
864/* support of 32bit userspace on 64bit platforms */
865#ifdef CONFIG_COMPAT
866static long snd_compr_ioctl_compat(struct file *file, unsigned int cmd,
867 unsigned long arg)
868{
869 return snd_compr_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
870}
871#endif
872
b21c60a4
VK
873static const struct file_operations snd_compr_file_ops = {
874 .owner = THIS_MODULE,
875 .open = snd_compr_open,
876 .release = snd_compr_free,
877 .write = snd_compr_write,
878 .read = snd_compr_read,
879 .unlocked_ioctl = snd_compr_ioctl,
c1036889
RL
880#ifdef CONFIG_COMPAT
881 .compat_ioctl = snd_compr_ioctl_compat,
882#endif
b21c60a4
VK
883 .mmap = snd_compr_mmap,
884 .poll = snd_compr_poll,
885};
886
887static int snd_compress_dev_register(struct snd_device *device)
888{
889 int ret = -EINVAL;
890 char str[16];
891 struct snd_compr *compr;
892
893 if (snd_BUG_ON(!device || !device->device_data))
894 return -EBADFD;
895 compr = device->device_data;
896
b21c60a4
VK
897 pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
898 compr->direction);
899 /* register compressed device */
40a4b263
TI
900 ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
901 compr->card, compr->device,
902 &snd_compr_file_ops, compr, &compr->dev);
b21c60a4
VK
903 if (ret < 0) {
904 pr_err("snd_register_device failed\n %d", ret);
905 return ret;
906 }
907 return ret;
908
909}
910
911static int snd_compress_dev_disconnect(struct snd_device *device)
912{
913 struct snd_compr *compr;
914
915 compr = device->device_data;
40a4b263 916 snd_unregister_device(&compr->dev);
b21c60a4
VK
917 return 0;
918}
919
31742724
RF
920#ifdef CONFIG_SND_VERBOSE_PROCFS
921static void snd_compress_proc_info_read(struct snd_info_entry *entry,
922 struct snd_info_buffer *buffer)
923{
924 struct snd_compr *compr = (struct snd_compr *)entry->private_data;
925
926 snd_iprintf(buffer, "card: %d\n", compr->card->number);
927 snd_iprintf(buffer, "device: %d\n", compr->device);
928 snd_iprintf(buffer, "stream: %s\n",
929 compr->direction == SND_COMPRESS_PLAYBACK
930 ? "PLAYBACK" : "CAPTURE");
931 snd_iprintf(buffer, "id: %s\n", compr->id);
932}
933
934static int snd_compress_proc_init(struct snd_compr *compr)
935{
936 struct snd_info_entry *entry;
937 char name[16];
938
939 sprintf(name, "compr%i", compr->device);
940 entry = snd_info_create_card_entry(compr->card, name,
941 compr->card->proc_root);
942 if (!entry)
943 return -ENOMEM;
944 entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
945 if (snd_info_register(entry) < 0) {
946 snd_info_free_entry(entry);
947 return -ENOMEM;
948 }
949 compr->proc_root = entry;
950
951 entry = snd_info_create_card_entry(compr->card, "info",
952 compr->proc_root);
953 if (entry) {
954 snd_info_set_text_ops(entry, compr,
955 snd_compress_proc_info_read);
956 if (snd_info_register(entry) < 0) {
957 snd_info_free_entry(entry);
958 entry = NULL;
959 }
960 }
961 compr->proc_info_entry = entry;
962
963 return 0;
964}
965
966static void snd_compress_proc_done(struct snd_compr *compr)
967{
968 snd_info_free_entry(compr->proc_info_entry);
969 compr->proc_info_entry = NULL;
970 snd_info_free_entry(compr->proc_root);
971 compr->proc_root = NULL;
972}
e5241a8c
RF
973
974static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
975{
976 strlcpy(compr->id, id, sizeof(compr->id));
977}
31742724
RF
978#else
979static inline int snd_compress_proc_init(struct snd_compr *compr)
980{
981 return 0;
982}
983
984static inline void snd_compress_proc_done(struct snd_compr *compr)
985{
986}
e5241a8c
RF
987
988static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
989{
990}
31742724
RF
991#endif
992
04c5d5a4
TI
993static int snd_compress_dev_free(struct snd_device *device)
994{
995 struct snd_compr *compr;
996
997 compr = device->device_data;
31742724 998 snd_compress_proc_done(compr);
04c5d5a4
TI
999 put_device(&compr->dev);
1000 return 0;
1001}
1002
b21c60a4
VK
1003/*
1004 * snd_compress_new: create new compress device
1005 * @card: sound card pointer
1006 * @device: device number
1007 * @dirn: device direction, should be of type enum snd_compr_direction
1008 * @compr: compress device pointer
1009 */
1010int snd_compress_new(struct snd_card *card, int device,
e5241a8c 1011 int dirn, const char *id, struct snd_compr *compr)
b21c60a4
VK
1012{
1013 static struct snd_device_ops ops = {
04c5d5a4 1014 .dev_free = snd_compress_dev_free,
b21c60a4
VK
1015 .dev_register = snd_compress_dev_register,
1016 .dev_disconnect = snd_compress_dev_disconnect,
1017 };
31742724 1018 int ret;
b21c60a4
VK
1019
1020 compr->card = card;
1021 compr->device = device;
1022 compr->direction = dirn;
04c5d5a4 1023
e5241a8c
RF
1024 snd_compress_set_id(compr, id);
1025
04c5d5a4
TI
1026 snd_device_initialize(&compr->dev, card);
1027 dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
1028
31742724
RF
1029 ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
1030 if (ret == 0)
1031 snd_compress_proc_init(compr);
1032
1033 return ret;
b21c60a4
VK
1034}
1035EXPORT_SYMBOL_GPL(snd_compress_new);
1036
1037static int snd_compress_add_device(struct snd_compr *device)
1038{
1039 int ret;
1040
1041 if (!device->card)
1042 return -EINVAL;
1043
1044 /* register the card */
1045 ret = snd_card_register(device->card);
1046 if (ret)
1047 goto out;
1048 return 0;
1049
1050out:
1051 pr_err("failed with %d\n", ret);
1052 return ret;
1053
1054}
1055
1056static int snd_compress_remove_device(struct snd_compr *device)
1057{
1058 return snd_card_free(device->card);
1059}
1060
1061/**
1062 * snd_compress_register - register compressed device
1063 *
1064 * @device: compressed device to register
1065 */
1066int snd_compress_register(struct snd_compr *device)
1067{
1068 int retval;
1069
04c5d5a4 1070 if (device->name == NULL || device->ops == NULL)
b21c60a4
VK
1071 return -EINVAL;
1072
1073 pr_debug("Registering compressed device %s\n", device->name);
1074 if (snd_BUG_ON(!device->ops->open))
1075 return -EINVAL;
1076 if (snd_BUG_ON(!device->ops->free))
1077 return -EINVAL;
1078 if (snd_BUG_ON(!device->ops->set_params))
1079 return -EINVAL;
1080 if (snd_BUG_ON(!device->ops->trigger))
1081 return -EINVAL;
1082
1083 mutex_init(&device->lock);
1084
1085 /* register a compressed card */
1086 mutex_lock(&device_mutex);
1087 retval = snd_compress_add_device(device);
1088 mutex_unlock(&device_mutex);
1089 return retval;
1090}
1091EXPORT_SYMBOL_GPL(snd_compress_register);
1092
1093int snd_compress_deregister(struct snd_compr *device)
1094{
1095 pr_debug("Removing compressed device %s\n", device->name);
1096 mutex_lock(&device_mutex);
1097 snd_compress_remove_device(device);
1098 mutex_unlock(&device_mutex);
1099 return 0;
1100}
1101EXPORT_SYMBOL_GPL(snd_compress_deregister);
1102
1103static int __init snd_compress_init(void)
1104{
1105 return 0;
1106}
1107
1108static void __exit snd_compress_exit(void)
1109{
1110}
1111
1112module_init(snd_compress_init);
1113module_exit(snd_compress_exit);
1114
1115MODULE_DESCRIPTION("ALSA Compressed offload framework");
1116MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
1117MODULE_LICENSE("GPL v2");