OSDN Git Service

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