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