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