Staging: sst: Add runtime PM support
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
blob4b316ccab411788e2df54f1dda274de79b9815b1
1 /*
2 * intel_sst_interface.c - Intel SST Driver for audio engine
4 * Copyright (C) 2008-10 Intel Corp
5 * Authors: Vinod Koul <vinod.koul@intel.com>
6 * Harsha Priya <priya.harsha@intel.com>
7 * Dharageswari R <dharageswari.r@intel.com>
8 * Jeeja KP <jeeja.kp@intel.com>
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * This driver exposes the audio engine functionalities to the ALSA
26 * and middleware.
27 * Upper layer interfaces (MAD driver, MMF) to SST driver
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/pci.h>
33 #include <linux/fs.h>
34 #include <linux/uio.h>
35 #include <linux/aio.h>
36 #include <linux/uaccess.h>
37 #include <linux/firmware.h>
38 #include <linux/pm_runtime.h>
39 #include <linux/ioctl.h>
40 #include <linux/smp_lock.h>
41 #ifdef CONFIG_MRST_RAR_HANDLER
42 #include <linux/rar_register.h>
43 #include "../../../drivers/staging/memrar/memrar.h"
44 #endif
45 #include "intel_sst.h"
46 #include "intel_sst_ioctl.h"
47 #include "intel_sst_fw_ipc.h"
48 #include "intel_sst_common.h"
50 #define AM_MODULE 1
51 #define STREAM_MODULE 0
54 /**
55 * intel_sst_check_device - checks SST device
57 * This utility function checks the state of SST device and downlaods FW if
58 * not done, or resumes the device if suspended
61 static int intel_sst_check_device(void)
63 int retval = 0;
64 if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
65 pr_warn("Sound card not available\n");
66 return -EIO;
68 if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
69 pr_debug("Resuming from Suspended state\n");
70 retval = intel_sst_resume(sst_drv_ctx->pci);
71 if (retval) {
72 pr_debug("Resume Failed= %#x,abort\n", retval);
73 return retval;
77 if (sst_drv_ctx->sst_state == SST_UN_INIT) {
78 /* FW is not downloaded */
79 retval = sst_download_fw();
80 if (retval)
81 return -ENODEV;
82 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
83 retval = sst_drv_ctx->rx_time_slot_status;
84 if (retval != RX_TIMESLOT_UNINIT
85 && sst_drv_ctx->pmic_vendor != SND_NC)
86 sst_enable_rx_timeslot(retval);
89 return 0;
92 /**
93 * intel_sst_open - opens a handle to driver
95 * @i_node: inode structure
96 * @file_ptr:pointer to file
98 * This function is called by OS when a user space component
99 * tries to get a driver handle. Only one handle at a time
100 * will be allowed
102 int intel_sst_open(struct inode *i_node, struct file *file_ptr)
104 unsigned int retval;
106 mutex_lock(&sst_drv_ctx->stream_lock);
107 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
108 retval = intel_sst_check_device();
109 if (retval) {
110 pm_runtime_put(&sst_drv_ctx->pci->dev);
111 mutex_unlock(&sst_drv_ctx->stream_lock);
112 return retval;
115 if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
116 struct ioctl_pvt_data *data =
117 kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
118 if (!data) {
119 pm_runtime_put(&sst_drv_ctx->pci->dev);
120 mutex_unlock(&sst_drv_ctx->stream_lock);
121 return -ENOMEM;
124 sst_drv_ctx->encoded_cnt++;
125 mutex_unlock(&sst_drv_ctx->stream_lock);
126 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
127 data->str_id = 0;
128 file_ptr->private_data = (void *)data;
129 pr_debug("pvt_id handle = %d!\n", data->pvt_id);
130 } else {
131 retval = -EUSERS;
132 pm_runtime_put(&sst_drv_ctx->pci->dev);
133 mutex_unlock(&sst_drv_ctx->stream_lock);
135 return retval;
139 * intel_sst_open_cntrl - opens a handle to driver
141 * @i_node: inode structure
142 * @file_ptr:pointer to file
144 * This function is called by OS when a user space component
145 * tries to get a driver handle to /dev/intel_sst_control.
146 * Only one handle at a time will be allowed
147 * This is for control operations only
149 int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
151 unsigned int retval;
153 /* audio manager open */
154 mutex_lock(&sst_drv_ctx->stream_lock);
155 pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
156 retval = intel_sst_check_device();
157 if (retval) {
158 pm_runtime_put(&sst_drv_ctx->pci->dev);
159 mutex_unlock(&sst_drv_ctx->stream_lock);
160 return retval;
163 if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
164 sst_drv_ctx->am_cnt++;
165 pr_debug("AM handle opened...\n");
166 file_ptr->private_data = NULL;
167 } else {
168 retval = -EACCES;
169 pm_runtime_put(&sst_drv_ctx->pci->dev);
172 mutex_unlock(&sst_drv_ctx->stream_lock);
173 return retval;
177 * intel_sst_release - releases a handle to driver
179 * @i_node: inode structure
180 * @file_ptr: pointer to file
182 * This function is called by OS when a user space component
183 * tries to release a driver handle.
185 int intel_sst_release(struct inode *i_node, struct file *file_ptr)
187 struct ioctl_pvt_data *data = file_ptr->private_data;
189 pr_debug("Release called, closing app handle\n");
190 mutex_lock(&sst_drv_ctx->stream_lock);
191 sst_drv_ctx->encoded_cnt--;
192 sst_drv_ctx->stream_cnt--;
193 pm_runtime_put(&sst_drv_ctx->pci->dev);
194 mutex_unlock(&sst_drv_ctx->stream_lock);
195 free_stream_context(data->str_id);
196 kfree(data);
197 return 0;
200 int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
202 /* audio manager close */
203 mutex_lock(&sst_drv_ctx->stream_lock);
204 sst_drv_ctx->am_cnt--;
205 pm_runtime_put(&sst_drv_ctx->pci->dev);
206 mutex_unlock(&sst_drv_ctx->stream_lock);
207 pr_debug("AM handle closed\n");
208 return 0;
212 * intel_sst_mmap - mmaps a kernel buffer to user space for copying data
214 * @vma: vm area structure instance
215 * @file_ptr: pointer to file
217 * This function is called by OS when a user space component
218 * tries to get mmap memory from driver
220 int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
222 int retval, length;
223 struct ioctl_pvt_data *data =
224 (struct ioctl_pvt_data *)file_ptr->private_data;
225 int str_id = data->str_id;
226 void *mem_area;
228 retval = sst_validate_strid(str_id);
229 if (retval)
230 return -EINVAL;
232 length = vma->vm_end - vma->vm_start;
233 pr_debug("called for stream %d length 0x%x\n", str_id, length);
235 if (length > sst_drv_ctx->mmap_len)
236 return -ENOMEM;
237 if (!sst_drv_ctx->mmap_mem)
238 return -EIO;
240 /* round it up to the page bondary */
241 /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
242 + PAGE_SIZE - 1) & PAGE_MASK);*/
243 mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
245 /* map the whole physically contiguous area in one piece */
246 retval = remap_pfn_range(vma,
247 vma->vm_start,
248 virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
249 length,
250 vma->vm_page_prot);
251 if (retval)
252 sst_drv_ctx->streams[str_id].mmapped = false;
253 else
254 sst_drv_ctx->streams[str_id].mmapped = true;
256 pr_debug("mmap ret 0x%x\n", retval);
257 return retval;
260 /* sets mmap data buffers to play/capture*/
261 static int intel_sst_mmap_play_capture(u32 str_id,
262 struct snd_sst_mmap_buffs *mmap_buf)
264 struct sst_stream_bufs *bufs;
265 int retval, i;
266 struct stream_info *stream;
267 struct snd_sst_mmap_buff_entry *buf_entry;
268 struct snd_sst_mmap_buff_entry *tmp_buf;
270 pr_debug("called for str_id %d\n", str_id);
271 retval = sst_validate_strid(str_id);
272 if (retval)
273 return -EINVAL;
275 stream = &sst_drv_ctx->streams[str_id];
276 if (stream->mmapped != true)
277 return -EIO;
279 if (stream->status == STREAM_UN_INIT ||
280 stream->status == STREAM_DECODE) {
281 return -EBADRQC;
283 stream->curr_bytes = 0;
284 stream->cumm_bytes = 0;
286 tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
287 if (!tmp_buf)
288 return -ENOMEM;
289 if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
290 mmap_buf->entries * sizeof(*tmp_buf))) {
291 retval = -EFAULT;
292 goto out_free;
295 pr_debug("new buffers count %d status %d\n",
296 mmap_buf->entries, stream->status);
297 buf_entry = tmp_buf;
298 for (i = 0; i < mmap_buf->entries; i++) {
299 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
300 if (!bufs) {
301 retval = -ENOMEM;
302 goto out_free;
304 bufs->size = buf_entry->size;
305 bufs->offset = buf_entry->offset;
306 bufs->addr = sst_drv_ctx->mmap_mem;
307 bufs->in_use = false;
308 buf_entry++;
309 /* locking here */
310 mutex_lock(&stream->lock);
311 list_add_tail(&bufs->node, &stream->bufs);
312 mutex_unlock(&stream->lock);
315 mutex_lock(&stream->lock);
316 stream->data_blk.condition = false;
317 stream->data_blk.ret_code = 0;
318 if (stream->status == STREAM_INIT &&
319 stream->prev != STREAM_UN_INIT &&
320 stream->need_draining != true) {
321 stream->prev = stream->status;
322 stream->status = STREAM_RUNNING;
323 if (stream->ops == STREAM_OPS_PLAYBACK) {
324 if (sst_play_frame(str_id) < 0) {
325 pr_warn("play frames fail\n");
326 mutex_unlock(&stream->lock);
327 retval = -EIO;
328 goto out_free;
330 } else if (stream->ops == STREAM_OPS_CAPTURE) {
331 if (sst_capture_frame(str_id) < 0) {
332 pr_warn("capture frame fail\n");
333 mutex_unlock(&stream->lock);
334 retval = -EIO;
335 goto out_free;
339 mutex_unlock(&stream->lock);
340 /* Block the call for reply */
341 if (!list_empty(&stream->bufs)) {
342 stream->data_blk.on = true;
343 retval = sst_wait_interruptible(sst_drv_ctx,
344 &stream->data_blk);
347 if (retval >= 0)
348 retval = stream->cumm_bytes;
349 pr_debug("end of play/rec ioctl bytes = %d!!\n", retval);
351 out_free:
352 kfree(tmp_buf);
353 return retval;
356 /*sets user data buffers to play/capture*/
357 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
359 int retval;
361 stream->data_blk.ret_code = 0;
362 stream->data_blk.on = true;
363 stream->data_blk.condition = false;
365 mutex_lock(&stream->lock);
366 if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
367 /* stream is started */
368 stream->prev = stream->status;
369 stream->status = STREAM_RUNNING;
372 if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
373 /* stream is not started yet */
374 pr_debug("Stream isn't in started state %d, prev %d\n",
375 stream->status, stream->prev);
376 } else if ((stream->status == STREAM_RUNNING ||
377 stream->status == STREAM_PAUSED) &&
378 stream->need_draining != true) {
379 /* stream is started */
380 if (stream->ops == STREAM_OPS_PLAYBACK ||
381 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
382 if (sst_play_frame(str_id) < 0) {
383 pr_warn("play frames failed\n");
384 mutex_unlock(&stream->lock);
385 return -EIO;
387 } else if (stream->ops == STREAM_OPS_CAPTURE) {
388 if (sst_capture_frame(str_id) < 0) {
389 pr_warn("capture frames failed\n");
390 mutex_unlock(&stream->lock);
391 return -EIO;
394 } else {
395 mutex_unlock(&stream->lock);
396 return -EIO;
398 mutex_unlock(&stream->lock);
399 /* Block the call for reply */
401 retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
402 if (retval) {
403 stream->status = STREAM_INIT;
404 pr_debug("wait returned error...\n");
406 return retval;
409 /* fills kernel list with buffer addresses for SST DSP driver to process*/
410 static int snd_sst_fill_kernel_list(struct stream_info *stream,
411 const struct iovec *iovec, unsigned long nr_segs,
412 struct list_head *copy_to_list)
414 struct sst_stream_bufs *stream_bufs;
415 unsigned long index, mmap_len;
416 unsigned char __user *bufp;
417 unsigned long size, copied_size;
418 int retval = 0, add_to_list = 0;
419 static int sent_offset;
420 static unsigned long sent_index;
422 stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
423 if (!stream_bufs)
424 return -ENOMEM;
425 stream_bufs->addr = sst_drv_ctx->mmap_mem;
426 #ifdef CONFIG_MRST_RAR_HANDLER
427 if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
428 for (index = stream->sg_index; index < nr_segs; index++) {
429 __u32 rar_handle;
430 struct sst_stream_bufs *stream_bufs =
431 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
433 stream->sg_index = index;
434 if (!stream_bufs)
435 return -ENOMEM;
436 if (copy_from_user((void *) &rar_handle,
437 iovec[index].iov_base,
438 sizeof(__u32)))
439 return -EFAULT;
440 stream_bufs->addr = (char *)rar_handle;
441 stream_bufs->in_use = false;
442 stream_bufs->size = iovec[0].iov_len;
443 /* locking here */
444 mutex_lock(&stream->lock);
445 list_add_tail(&stream_bufs->node, &stream->bufs);
446 mutex_unlock(&stream->lock);
448 stream->sg_index = index;
449 return retval;
451 #endif
452 mmap_len = sst_drv_ctx->mmap_len;
453 stream_bufs->addr = sst_drv_ctx->mmap_mem;
454 bufp = stream->cur_ptr;
456 copied_size = 0;
458 if (!stream->sg_index)
459 sent_index = sent_offset = 0;
461 for (index = stream->sg_index; index < nr_segs; index++) {
462 stream->sg_index = index;
463 if (!stream->cur_ptr)
464 bufp = iovec[index].iov_base;
466 size = ((unsigned long)iovec[index].iov_base
467 + iovec[index].iov_len) - (unsigned long) bufp;
469 if ((copied_size + size) > mmap_len)
470 size = mmap_len - copied_size;
473 if (stream->ops == STREAM_OPS_PLAYBACK) {
474 if (copy_from_user((void *)
475 (stream_bufs->addr + copied_size),
476 bufp, size)) {
477 /* Clean up the list and return error code */
478 retval = -EFAULT;
479 break;
481 } else if (stream->ops == STREAM_OPS_CAPTURE) {
482 struct snd_sst_user_cap_list *entry =
483 kzalloc(sizeof(*entry), GFP_KERNEL);
485 if (!entry) {
486 kfree(stream_bufs);
487 return -ENOMEM;
489 entry->iov_index = index;
490 entry->iov_offset = (unsigned long) bufp -
491 (unsigned long)iovec[index].iov_base;
492 entry->offset = copied_size;
493 entry->size = size;
494 list_add_tail(&entry->node, copy_to_list);
497 stream->cur_ptr = bufp + size;
499 if (((unsigned long)iovec[index].iov_base
500 + iovec[index].iov_len) <
501 ((unsigned long)iovec[index].iov_base)) {
502 pr_debug("Buffer overflows\n");
503 kfree(stream_bufs);
504 return -EINVAL;
507 if (((unsigned long)iovec[index].iov_base
508 + iovec[index].iov_len) ==
509 (unsigned long)stream->cur_ptr) {
510 stream->cur_ptr = NULL;
511 stream->sg_index++;
514 copied_size += size;
515 pr_debug("copied_size - %lx\n", copied_size);
516 if ((copied_size >= mmap_len) ||
517 (stream->sg_index == nr_segs)) {
518 add_to_list = 1;
521 if (add_to_list) {
522 stream_bufs->in_use = false;
523 stream_bufs->size = copied_size;
524 /* locking here */
525 mutex_lock(&stream->lock);
526 list_add_tail(&stream_bufs->node, &stream->bufs);
527 mutex_unlock(&stream->lock);
528 break;
531 return retval;
534 /* This function copies the captured data returned from SST DSP engine
535 * to the user buffers*/
536 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
537 const struct iovec *iovec,
538 struct list_head *copy_to_list)
540 struct snd_sst_user_cap_list *entry, *_entry;
541 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
542 int retval = 0;
544 /* copy sent buffers */
545 pr_debug("capture stream copying to user now...\n");
546 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
547 if (kbufs->in_use == true) {
548 /* copy to user */
549 list_for_each_entry_safe(entry, _entry,
550 copy_to_list, node) {
551 if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
552 kbufs->addr + entry->offset,
553 entry->size)) {
554 /* Clean up the list and return error */
555 retval = -EFAULT;
556 break;
558 list_del(&entry->node);
559 kfree(entry);
563 pr_debug("end of cap copy\n");
564 return retval;
568 * snd_sst_userbufs_play_cap - constructs the list from user buffers
570 * @iovec:pointer to iovec structure
571 * @nr_segs:number entries in the iovec structure
572 * @str_id:stream id
573 * @stream:pointer to stream_info structure
575 * This function will traverse the user list and copy the data to the kernel
576 * space buffers.
578 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
579 unsigned long nr_segs, unsigned int str_id,
580 struct stream_info *stream)
582 int retval;
583 LIST_HEAD(copy_to_list);
586 retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
587 &copy_to_list);
589 retval = intel_sst_play_capture(stream, str_id);
590 if (retval < 0)
591 return retval;
593 if (stream->ops == STREAM_OPS_CAPTURE) {
594 retval = snd_sst_copy_userbuf_capture(stream, iovec,
595 &copy_to_list);
597 return retval;
600 /* This function is common function across read/write
601 for user buffers called from system calls*/
602 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
603 size_t count)
605 int retval;
606 struct stream_info *stream;
607 struct iovec iovec;
608 unsigned long nr_segs;
610 retval = sst_validate_strid(str_id);
611 if (retval)
612 return -EINVAL;
613 stream = &sst_drv_ctx->streams[str_id];
614 if (stream->mmapped == true) {
615 pr_warn("user write and stream is mapped\n");
616 return -EIO;
618 if (!count)
619 return -EINVAL;
620 stream->curr_bytes = 0;
621 stream->cumm_bytes = 0;
622 /* copy user buf details */
623 pr_debug("new buffers %p, copy size %d, status %d\n" ,
624 buf, (int) count, (int) stream->status);
626 stream->buf_type = SST_BUF_USER_STATIC;
627 iovec.iov_base = buf;
628 iovec.iov_len = count;
629 nr_segs = 1;
631 do {
632 retval = snd_sst_userbufs_play_cap(
633 &iovec, nr_segs, str_id, stream);
634 if (retval < 0)
635 break;
637 } while (stream->sg_index < nr_segs);
639 stream->sg_index = 0;
640 stream->cur_ptr = NULL;
641 if (retval >= 0)
642 retval = stream->cumm_bytes;
643 pr_debug("end of play/rec bytes = %d!!\n", retval);
644 return retval;
647 /***
648 * intel_sst_write - This function is called when user tries to play out data
650 * @file_ptr:pointer to file
651 * @buf:user buffer to be played out
652 * @count:size of tthe buffer
653 * @offset:offset to start from
655 * writes the encoded data into DSP
657 int intel_sst_write(struct file *file_ptr, const char __user *buf,
658 size_t count, loff_t *offset)
660 struct ioctl_pvt_data *data = file_ptr->private_data;
661 int str_id = data->str_id;
662 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
664 pr_debug("called for %d\n", str_id);
665 if (stream->status == STREAM_UN_INIT ||
666 stream->status == STREAM_DECODE) {
667 return -EBADRQC;
669 return intel_sst_read_write(str_id, (char __user *)buf, count);
673 * intel_sst_aio_write - write buffers
675 * @kiocb:pointer to a structure containing file pointer
676 * @iov:list of user buffer to be played out
677 * @nr_segs:number of entries
678 * @offset:offset to start from
680 * This function is called when user tries to play out multiple data buffers
682 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
683 unsigned long nr_segs, loff_t offset)
685 int retval;
686 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
687 int str_id = data->str_id;
688 struct stream_info *stream;
690 pr_debug("entry - %ld\n", nr_segs);
692 if (is_sync_kiocb(kiocb) == false)
693 return -EINVAL;
695 pr_debug("called for str_id %d\n", str_id);
696 retval = sst_validate_strid(str_id);
697 if (retval)
698 return -EINVAL;
699 stream = &sst_drv_ctx->streams[str_id];
700 if (stream->mmapped == true)
701 return -EIO;
702 if (stream->status == STREAM_UN_INIT ||
703 stream->status == STREAM_DECODE) {
704 return -EBADRQC;
706 stream->curr_bytes = 0;
707 stream->cumm_bytes = 0;
708 pr_debug("new segs %ld, offset %d, status %d\n" ,
709 nr_segs, (int) offset, (int) stream->status);
710 stream->buf_type = SST_BUF_USER_STATIC;
711 do {
712 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
713 str_id, stream);
714 if (retval < 0)
715 break;
717 } while (stream->sg_index < nr_segs);
719 stream->sg_index = 0;
720 stream->cur_ptr = NULL;
721 if (retval >= 0)
722 retval = stream->cumm_bytes;
723 pr_debug("end of play/rec bytes = %d!!\n", retval);
724 return retval;
728 * intel_sst_read - read the encoded data
730 * @file_ptr: pointer to file
731 * @buf: user buffer to be filled with captured data
732 * @count: size of tthe buffer
733 * @offset: offset to start from
735 * This function is called when user tries to capture data
737 int intel_sst_read(struct file *file_ptr, char __user *buf,
738 size_t count, loff_t *offset)
740 struct ioctl_pvt_data *data = file_ptr->private_data;
741 int str_id = data->str_id;
742 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
744 pr_debug("called for %d\n", str_id);
745 if (stream->status == STREAM_UN_INIT ||
746 stream->status == STREAM_DECODE)
747 return -EBADRQC;
748 return intel_sst_read_write(str_id, buf, count);
752 * intel_sst_aio_read - aio read
754 * @kiocb: pointer to a structure containing file pointer
755 * @iov: list of user buffer to be filled with captured
756 * @nr_segs: number of entries
757 * @offset: offset to start from
759 * This function is called when user tries to capture out multiple data buffers
761 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
762 unsigned long nr_segs, loff_t offset)
764 int retval;
765 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
766 int str_id = data->str_id;
767 struct stream_info *stream;
769 pr_debug("entry - %ld\n", nr_segs);
771 if (is_sync_kiocb(kiocb) == false) {
772 pr_debug("aio_read from user space is not allowed\n");
773 return -EINVAL;
776 pr_debug("called for str_id %d\n", str_id);
777 retval = sst_validate_strid(str_id);
778 if (retval)
779 return -EINVAL;
780 stream = &sst_drv_ctx->streams[str_id];
781 if (stream->mmapped == true)
782 return -EIO;
783 if (stream->status == STREAM_UN_INIT ||
784 stream->status == STREAM_DECODE)
785 return -EBADRQC;
786 stream->curr_bytes = 0;
787 stream->cumm_bytes = 0;
789 pr_debug("new segs %ld, offset %d, status %d\n" ,
790 nr_segs, (int) offset, (int) stream->status);
791 stream->buf_type = SST_BUF_USER_STATIC;
792 do {
793 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
794 str_id, stream);
795 if (retval < 0)
796 break;
798 } while (stream->sg_index < nr_segs);
800 stream->sg_index = 0;
801 stream->cur_ptr = NULL;
802 if (retval >= 0)
803 retval = stream->cumm_bytes;
804 pr_debug("end of play/rec bytes = %d!!\n", retval);
805 return retval;
808 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
809 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
811 pr_debug("codec params:result = %d\n",
812 get_prm->codec_params.result);
813 pr_debug("codec params:stream = %d\n",
814 get_prm->codec_params.stream_id);
815 pr_debug("codec params:codec = %d\n",
816 get_prm->codec_params.codec);
817 pr_debug("codec params:ops = %d\n",
818 get_prm->codec_params.ops);
819 pr_debug("codec params:stream_type = %d\n",
820 get_prm->codec_params.stream_type);
821 pr_debug("pcmparams:sfreq = %d\n",
822 get_prm->pcm_params.sfreq);
823 pr_debug("pcmparams:num_chan = %d\n",
824 get_prm->pcm_params.num_chan);
825 pr_debug("pcmparams:pcm_wd_sz = %d\n",
826 get_prm->pcm_params.pcm_wd_sz);
827 return;
831 * intel_sst_ioctl - receives the device ioctl's
832 * @file_ptr:pointer to file
833 * @cmd:Ioctl cmd
834 * @arg:data
836 * This function is called by OS when a user space component
837 * sends an Ioctl to SST driver
839 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
841 int retval = 0;
842 struct ioctl_pvt_data *data = NULL;
843 int str_id = 0, minor = 0;
845 data = file_ptr->private_data;
846 if (data) {
847 minor = 0;
848 str_id = data->str_id;
849 } else
850 minor = 1;
852 if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
853 return -EBUSY;
855 switch (_IOC_NR(cmd)) {
856 case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
857 pr_debug("IOCTL_PAUSE received for %d!\n", str_id);
858 if (minor != STREAM_MODULE) {
859 retval = -EBADRQC;
860 break;
862 retval = sst_pause_stream(str_id);
863 break;
865 case _IOC_NR(SNDRV_SST_STREAM_RESUME):
866 pr_debug("SNDRV_SST_IOCTL_RESUME received!\n");
867 if (minor != STREAM_MODULE) {
868 retval = -EBADRQC;
869 break;
871 retval = sst_resume_stream(str_id);
872 break;
874 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
875 struct snd_sst_params str_param;
877 pr_debug("IOCTL_SET_PARAMS received!\n");
878 if (minor != STREAM_MODULE) {
879 retval = -EBADRQC;
880 break;
883 if (copy_from_user(&str_param, (void __user *)arg,
884 sizeof(str_param))) {
885 retval = -EFAULT;
886 break;
889 if (!str_id) {
891 retval = sst_get_stream(&str_param);
892 if (retval > 0) {
893 struct stream_info *str_info;
894 char __user *dest;
896 sst_drv_ctx->stream_cnt++;
897 data->str_id = retval;
898 str_info = &sst_drv_ctx->streams[retval];
899 str_info->src = SST_DRV;
900 dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
901 retval = copy_to_user(dest, &retval, sizeof(__u32));
902 if (retval)
903 retval = -EFAULT;
904 } else {
905 if (retval == -SST_ERR_INVALID_PARAMS)
906 retval = -EINVAL;
908 } else {
909 pr_debug("SET_STREAM_PARAMS received!\n");
910 /* allocated set params only */
911 retval = sst_set_stream_param(str_id, &str_param);
912 /* Block the call for reply */
913 if (!retval) {
914 int sfreq = 0, word_size = 0, num_channel = 0;
915 sfreq = str_param.sparams.uc.pcm_params.sfreq;
916 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
917 num_channel = str_param.sparams.uc.pcm_params.num_chan;
918 if (str_param.ops == STREAM_OPS_CAPTURE) {
919 sst_drv_ctx->scard_ops->\
920 set_pcm_audio_params(sfreq,
921 word_size, num_channel);
925 break;
927 case _IOC_NR(SNDRV_SST_SET_VOL): {
928 struct snd_sst_vol set_vol;
930 if (copy_from_user(&set_vol, (void __user *)arg,
931 sizeof(set_vol))) {
932 pr_debug("copy failed\n");
933 retval = -EFAULT;
934 break;
936 pr_debug("SET_VOLUME recieved for %d!\n",
937 set_vol.stream_id);
938 if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
939 pr_debug("invalid operation!\n");
940 retval = -EPERM;
941 break;
943 retval = sst_set_vol(&set_vol);
944 break;
946 case _IOC_NR(SNDRV_SST_GET_VOL): {
947 struct snd_sst_vol get_vol;
949 if (copy_from_user(&get_vol, (void __user *)arg,
950 sizeof(get_vol))) {
951 retval = -EFAULT;
952 break;
954 pr_debug("IOCTL_GET_VOLUME recieved for stream = %d!\n",
955 get_vol.stream_id);
956 if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
957 pr_debug("invalid operation!\n");
958 retval = -EPERM;
959 break;
961 retval = sst_get_vol(&get_vol);
962 if (retval) {
963 retval = -EIO;
964 break;
966 pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
967 get_vol.stream_id, get_vol.volume,
968 get_vol.ramp_duration, get_vol.ramp_type);
969 if (copy_to_user((struct snd_sst_vol __user *)arg,
970 &get_vol, sizeof(get_vol))) {
971 retval = -EFAULT;
972 break;
974 /*sst_print_get_vol_info(str_id, &get_vol);*/
975 break;
978 case _IOC_NR(SNDRV_SST_MUTE): {
979 struct snd_sst_mute set_mute;
981 if (copy_from_user(&set_mute, (void __user *)arg,
982 sizeof(set_mute))) {
983 retval = -EFAULT;
984 break;
986 pr_debug("SNDRV_SST_SET_VOLUME recieved for %d!\n",
987 set_mute.stream_id);
988 if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
989 retval = -EPERM;
990 break;
992 retval = sst_set_mute(&set_mute);
993 break;
995 case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
996 struct snd_sst_get_stream_params get_params;
998 pr_debug("IOCTL_GET_PARAMS received!\n");
999 if (minor != 0) {
1000 retval = -EBADRQC;
1001 break;
1004 retval = sst_get_stream_params(str_id, &get_params);
1005 if (retval) {
1006 retval = -EIO;
1007 break;
1009 if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
1010 &get_params, sizeof(get_params))) {
1011 retval = -EFAULT;
1012 break;
1014 sst_print_stream_params(&get_params);
1015 break;
1018 case _IOC_NR(SNDRV_SST_MMAP_PLAY):
1019 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
1020 struct snd_sst_mmap_buffs mmap_buf;
1022 pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n");
1023 if (minor != STREAM_MODULE) {
1024 retval = -EBADRQC;
1025 break;
1027 if (copy_from_user(&mmap_buf, (void __user *)arg,
1028 sizeof(mmap_buf))) {
1029 retval = -EFAULT;
1030 break;
1032 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
1033 break;
1035 case _IOC_NR(SNDRV_SST_STREAM_DROP):
1036 pr_debug("SNDRV_SST_IOCTL_DROP received!\n");
1037 if (minor != STREAM_MODULE) {
1038 retval = -EINVAL;
1039 break;
1041 retval = sst_drop_stream(str_id);
1042 break;
1044 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1045 struct snd_sst_tstamp tstamp = {0};
1046 unsigned long long time, freq, mod;
1048 pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n");
1049 if (minor != STREAM_MODULE) {
1050 retval = -EBADRQC;
1051 break;
1053 memcpy_fromio(&tstamp,
1054 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1055 sizeof(tstamp));
1056 time = tstamp.samples_rendered;
1057 freq = (unsigned long long) tstamp.sampling_frequency;
1058 time = time * 1000; /* converting it to ms */
1059 mod = do_div(time, freq);
1060 if (copy_to_user((void __user *)arg, &time,
1061 sizeof(unsigned long long)))
1062 retval = -EFAULT;
1063 break;
1066 case _IOC_NR(SNDRV_SST_STREAM_START):{
1067 struct stream_info *stream;
1069 pr_debug("SNDRV_SST_STREAM_START received!\n");
1070 if (minor != STREAM_MODULE) {
1071 retval = -EINVAL;
1072 break;
1074 retval = sst_validate_strid(str_id);
1075 if (retval)
1076 break;
1077 stream = &sst_drv_ctx->streams[str_id];
1078 mutex_lock(&stream->lock);
1079 if (stream->status == STREAM_INIT &&
1080 stream->need_draining != true) {
1081 stream->prev = stream->status;
1082 stream->status = STREAM_RUNNING;
1083 if (stream->ops == STREAM_OPS_PLAYBACK ||
1084 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1085 retval = sst_play_frame(str_id);
1086 } else if (stream->ops == STREAM_OPS_CAPTURE)
1087 retval = sst_capture_frame(str_id);
1088 else {
1089 retval = -EINVAL;
1090 mutex_unlock(&stream->lock);
1091 break;
1093 if (retval < 0) {
1094 stream->status = STREAM_INIT;
1095 mutex_unlock(&stream->lock);
1096 break;
1098 } else {
1099 retval = -EINVAL;
1101 mutex_unlock(&stream->lock);
1102 break;
1105 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1106 struct snd_sst_target_device target_device;
1108 pr_debug("SET_TARGET_DEVICE recieved!\n");
1109 if (copy_from_user(&target_device, (void __user *)arg,
1110 sizeof(target_device))) {
1111 retval = -EFAULT;
1112 break;
1114 if (minor != AM_MODULE) {
1115 retval = -EBADRQC;
1116 break;
1118 retval = sst_target_device_select(&target_device);
1119 break;
1122 case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1123 struct snd_sst_driver_info info;
1125 pr_debug("SNDRV_SST_DRIVER_INFO recived\n");
1126 info.version = SST_VERSION_NUM;
1127 /* hard coding, shud get sumhow later */
1128 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1129 sst_drv_ctx->encoded_cnt;
1130 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1131 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1132 info.max_enc_streams = MAX_ENC_STREAM;
1133 info.buf_per_stream = sst_drv_ctx->mmap_len;
1134 if (copy_to_user((void __user *)arg, &info,
1135 sizeof(info)))
1136 retval = -EFAULT;
1137 break;
1140 case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1141 struct snd_sst_dbufs param;
1142 struct snd_sst_dbufs dbufs_local;
1143 struct snd_sst_buffs ibufs, obufs;
1144 struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
1145 char __user *dest;
1147 pr_debug("SNDRV_SST_STREAM_DECODE received\n");
1148 if (minor != STREAM_MODULE) {
1149 retval = -EBADRQC;
1150 break;
1152 if (copy_from_user(&param, (void __user *)arg,
1153 sizeof(param))) {
1154 retval = -EFAULT;
1155 break;
1158 dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
1159 dbufs_local.output_bytes_produced =
1160 param.output_bytes_produced;
1162 if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
1163 retval = -EFAULT;
1164 break;
1166 if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
1167 retval = -EFAULT;
1168 break;
1171 ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
1172 obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
1173 if (!ibuf_tmp || !obuf_tmp) {
1174 retval = -ENOMEM;
1175 goto free_iobufs;
1178 if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
1179 ibufs.entries * sizeof(*ibuf_tmp))) {
1180 retval = -EFAULT;
1181 goto free_iobufs;
1183 ibufs.buff_entry = ibuf_tmp;
1184 dbufs_local.ibufs = &ibufs;
1186 if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
1187 obufs.entries * sizeof(*obuf_tmp))) {
1188 retval = -EFAULT;
1189 goto free_iobufs;
1191 obufs.buff_entry = obuf_tmp;
1192 dbufs_local.obufs = &obufs;
1194 retval = sst_decode(str_id, &dbufs_local);
1195 if (retval) {
1196 retval = -EAGAIN;
1197 goto free_iobufs;
1200 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1201 if (copy_to_user(dest,
1202 &dbufs_local.input_bytes_consumed,
1203 sizeof(unsigned long long))) {
1204 retval = -EFAULT;
1205 goto free_iobufs;
1208 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1209 if (copy_to_user(dest,
1210 &dbufs_local.output_bytes_produced,
1211 sizeof(unsigned long long))) {
1212 retval = -EFAULT;
1213 goto free_iobufs;
1215 free_iobufs:
1216 kfree(ibuf_tmp);
1217 kfree(obuf_tmp);
1218 break;
1221 case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1222 pr_debug("SNDRV_SST_STREAM_DRAIN received\n");
1223 if (minor != STREAM_MODULE) {
1224 retval = -EINVAL;
1225 break;
1227 retval = sst_drain_stream(str_id);
1228 break;
1230 case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1231 unsigned long long __user *bytes = (unsigned long long __user *)arg;
1232 struct snd_sst_tstamp tstamp = {0};
1234 pr_debug("STREAM_BYTES_DECODED received!\n");
1235 if (minor != STREAM_MODULE) {
1236 retval = -EINVAL;
1237 break;
1239 memcpy_fromio(&tstamp,
1240 sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1241 sizeof(tstamp));
1242 if (copy_to_user(bytes, &tstamp.bytes_processed,
1243 sizeof(*bytes)))
1244 retval = -EFAULT;
1245 break;
1247 case _IOC_NR(SNDRV_SST_FW_INFO): {
1248 struct snd_sst_fw_info *fw_info;
1250 pr_debug("SNDRV_SST_FW_INFO received\n");
1252 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1253 if (!fw_info) {
1254 retval = -ENOMEM;
1255 break;
1257 retval = sst_get_fw_info(fw_info);
1258 if (retval) {
1259 retval = -EIO;
1260 kfree(fw_info);
1261 break;
1263 if (copy_to_user((struct snd_sst_dbufs __user *)arg,
1264 fw_info, sizeof(*fw_info))) {
1265 kfree(fw_info);
1266 retval = -EFAULT;
1267 break;
1269 /*sst_print_fw_info(fw_info);*/
1270 kfree(fw_info);
1271 break;
1273 default:
1274 retval = -EINVAL;
1276 pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval);
1277 return retval;