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