Staging: intel_sst: return -EFAULT if copy_to_user() fails
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
blobb92ce377b1023aaab321e8fddd2c9bc0d5e70614
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 #include <linux/pci.h>
31 #include <linux/fs.h>
32 #include <linux/uio.h>
33 #include <linux/aio.h>
34 #include <linux/uaccess.h>
35 #include <linux/firmware.h>
36 #include <linux/ioctl.h>
37 #include <linux/smp_lock.h>
38 #ifdef CONFIG_MRST_RAR_HANDLER
39 #include <linux/rar_register.h>
40 #include "../../../drivers/staging/memrar/memrar.h"
41 #endif
42 #include "intel_sst.h"
43 #include "intel_sst_ioctl.h"
44 #include "intel_sst_fw_ipc.h"
45 #include "intel_sst_common.h"
47 #define AM_MODULE 1
48 #define STREAM_MODULE 0
51 /**
52 * intel_sst_check_device - checks SST device
54 * This utility function checks the state of SST device and downlaods FW if
55 * not done, or resumes the device if suspended
58 static int intel_sst_check_device(void)
60 int retval = 0;
61 if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
62 pr_warn("sst: Sound card not availble\n ");
63 return -EIO;
65 if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
66 pr_debug("sst: Resuming from Suspended state\n");
67 retval = intel_sst_resume(sst_drv_ctx->pci);
68 if (retval) {
69 pr_debug("sst: Resume Failed= %#x,abort\n", retval);
70 return retval;
74 if (sst_drv_ctx->sst_state == SST_UN_INIT) {
75 /* FW is not downloaded */
76 retval = sst_download_fw();
77 if (retval)
78 return -ENODEV;
79 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
80 retval = sst_drv_ctx->rx_time_slot_status;
81 if (retval != RX_TIMESLOT_UNINIT
82 && sst_drv_ctx->pmic_vendor != SND_NC)
83 sst_enable_rx_timeslot(retval);
86 return 0;
89 /**
90 * intel_sst_open - opens a handle to driver
92 * @i_node: inode structure
93 * @file_ptr:pointer to file
95 * This function is called by OS when a user space component
96 * tries to get a driver handle. Only one handle at a time
97 * will be allowed
99 int intel_sst_open(struct inode *i_node, struct file *file_ptr)
101 int retval = intel_sst_check_device();
102 if (retval)
103 return retval;
105 mutex_lock(&sst_drv_ctx->stream_lock);
106 if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
107 struct ioctl_pvt_data *data =
108 kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
109 if (!data) {
110 mutex_unlock(&sst_drv_ctx->stream_lock);
111 return -ENOMEM;
114 sst_drv_ctx->encoded_cnt++;
115 mutex_unlock(&sst_drv_ctx->stream_lock);
116 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
117 data->str_id = 0;
118 file_ptr->private_data = (void *)data;
119 pr_debug("sst: pvt_id handle = %d!\n", data->pvt_id);
120 } else {
121 retval = -EUSERS;
122 mutex_unlock(&sst_drv_ctx->stream_lock);
124 return retval;
128 * intel_sst_open_cntrl - opens a handle to driver
130 * @i_node: inode structure
131 * @file_ptr:pointer to file
133 * This function is called by OS when a user space component
134 * tries to get a driver handle to /dev/intel_sst_control.
135 * Only one handle at a time will be allowed
136 * This is for control operations only
138 int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
140 int retval = intel_sst_check_device();
141 if (retval)
142 return retval;
144 /* audio manager open */
145 mutex_lock(&sst_drv_ctx->stream_lock);
146 if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
147 sst_drv_ctx->am_cnt++;
148 pr_debug("sst: AM handle opened...\n");
149 file_ptr->private_data = NULL;
150 } else
151 retval = -EACCES;
153 mutex_unlock(&sst_drv_ctx->stream_lock);
154 return retval;
158 * intel_sst_release - releases a handle to driver
160 * @i_node: inode structure
161 * @file_ptr: pointer to file
163 * This function is called by OS when a user space component
164 * tries to release a driver handle.
166 int intel_sst_release(struct inode *i_node, struct file *file_ptr)
168 struct ioctl_pvt_data *data = file_ptr->private_data;
170 pr_debug("sst: Release called, closing app handle\n");
171 mutex_lock(&sst_drv_ctx->stream_lock);
172 sst_drv_ctx->encoded_cnt--;
173 sst_drv_ctx->stream_cnt--;
174 mutex_unlock(&sst_drv_ctx->stream_lock);
175 free_stream_context(data->str_id);
176 kfree(data);
177 return 0;
180 int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
182 /* audio manager close */
183 mutex_lock(&sst_drv_ctx->stream_lock);
184 sst_drv_ctx->am_cnt--;
185 mutex_unlock(&sst_drv_ctx->stream_lock);
186 pr_debug("sst: AM handle closed\n");
187 return 0;
191 * intel_sst_mmap - mmaps a kernel buffer to user space for copying data
193 * @vma: vm area structure instance
194 * @file_ptr: pointer to file
196 * This function is called by OS when a user space component
197 * tries to get mmap memory from driver
199 int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
201 int retval, length;
202 struct ioctl_pvt_data *data =
203 (struct ioctl_pvt_data *)file_ptr->private_data;
204 int str_id = data->str_id;
205 void *mem_area;
207 retval = sst_validate_strid(str_id);
208 if (retval)
209 return -EINVAL;
211 length = vma->vm_end - vma->vm_start;
212 pr_debug("sst: called for stream %d length 0x%x\n", str_id, length);
214 if (length > sst_drv_ctx->mmap_len)
215 return -ENOMEM;
216 if (!sst_drv_ctx->mmap_mem)
217 return -EIO;
219 /* round it up to the page bondary */
220 /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
221 + PAGE_SIZE - 1) & PAGE_MASK);*/
222 mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
224 /* map the whole physically contiguous area in one piece */
225 retval = remap_pfn_range(vma,
226 vma->vm_start,
227 virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
228 length,
229 vma->vm_page_prot);
230 if (retval)
231 sst_drv_ctx->streams[str_id].mmapped = false;
232 else
233 sst_drv_ctx->streams[str_id].mmapped = true;
235 pr_debug("sst: mmap ret 0x%x\n", retval);
236 return retval;
239 /* sets mmap data buffers to play/capture*/
240 static int intel_sst_mmap_play_capture(u32 str_id,
241 struct snd_sst_mmap_buffs *mmap_buf)
243 struct sst_stream_bufs *bufs;
244 int retval, i;
245 struct stream_info *stream;
246 struct snd_sst_mmap_buff_entry *buf_entry;
248 pr_debug("sst:called for str_id %d\n", str_id);
249 retval = sst_validate_strid(str_id);
250 if (retval)
251 return -EINVAL;
252 BUG_ON(!mmap_buf);
254 stream = &sst_drv_ctx->streams[str_id];
255 if (stream->mmapped != true)
256 return -EIO;
258 if (stream->status == STREAM_UN_INIT ||
259 stream->status == STREAM_DECODE) {
260 return -EBADRQC;
262 stream->curr_bytes = 0;
263 stream->cumm_bytes = 0;
265 pr_debug("sst:new buffers count %d status %d\n",
266 mmap_buf->entries, stream->status);
267 buf_entry = mmap_buf->buff;
268 for (i = 0; i < mmap_buf->entries; i++) {
269 BUG_ON(!buf_entry);
270 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
271 if (!bufs)
272 return -ENOMEM;
273 bufs->size = buf_entry->size;
274 bufs->offset = buf_entry->offset;
275 bufs->addr = sst_drv_ctx->mmap_mem;
276 bufs->in_use = false;
277 buf_entry++;
278 /* locking here */
279 mutex_lock(&stream->lock);
280 list_add_tail(&bufs->node, &stream->bufs);
281 mutex_unlock(&stream->lock);
284 mutex_lock(&stream->lock);
285 stream->data_blk.condition = false;
286 stream->data_blk.ret_code = 0;
287 if (stream->status == STREAM_INIT &&
288 stream->prev != STREAM_UN_INIT &&
289 stream->need_draining != true) {
290 stream->prev = stream->status;
291 stream->status = STREAM_RUNNING;
292 if (stream->ops == STREAM_OPS_PLAYBACK) {
293 if (sst_play_frame(str_id) < 0) {
294 pr_warn("sst: play frames fail\n");
295 mutex_unlock(&stream->lock);
296 return -EIO;
298 } else if (stream->ops == STREAM_OPS_CAPTURE) {
299 if (sst_capture_frame(str_id) < 0) {
300 pr_warn("sst: capture frame fail\n");
301 mutex_unlock(&stream->lock);
302 return -EIO;
306 mutex_unlock(&stream->lock);
307 /* Block the call for reply */
308 if (!list_empty(&stream->bufs)) {
309 stream->data_blk.on = true;
310 retval = sst_wait_interruptible(sst_drv_ctx,
311 &stream->data_blk);
314 if (retval >= 0)
315 retval = stream->cumm_bytes;
316 pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval);
317 return retval;
320 /*sets user data buffers to play/capture*/
321 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
323 int retval;
325 stream->data_blk.ret_code = 0;
326 stream->data_blk.on = true;
327 stream->data_blk.condition = false;
329 mutex_lock(&stream->lock);
330 if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
331 /* stream is started */
332 stream->prev = stream->status;
333 stream->status = STREAM_RUNNING;
336 if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
337 /* stream is not started yet */
338 pr_debug("sst: Stream isn't in started state %d, prev %d\n",
339 stream->status, stream->prev);
340 } else if ((stream->status == STREAM_RUNNING ||
341 stream->status == STREAM_PAUSED) &&
342 stream->need_draining != true) {
343 /* stream is started */
344 if (stream->ops == STREAM_OPS_PLAYBACK ||
345 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
346 if (sst_play_frame(str_id) < 0) {
347 pr_warn("sst: play frames failed\n");
348 mutex_unlock(&stream->lock);
349 return -EIO;
351 } else if (stream->ops == STREAM_OPS_CAPTURE) {
352 if (sst_capture_frame(str_id) < 0) {
353 pr_warn("sst: capture frames failed\n ");
354 mutex_unlock(&stream->lock);
355 return -EIO;
358 } else {
359 mutex_unlock(&stream->lock);
360 return -EIO;
362 mutex_unlock(&stream->lock);
363 /* Block the call for reply */
365 retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
366 if (retval) {
367 stream->status = STREAM_INIT;
368 pr_debug("sst: wait returned error...\n");
370 return retval;
373 /* fills kernel list with buffer addresses for SST DSP driver to process*/
374 static int snd_sst_fill_kernel_list(struct stream_info *stream,
375 const struct iovec *iovec, unsigned long nr_segs,
376 struct list_head *copy_to_list)
378 struct sst_stream_bufs *stream_bufs;
379 unsigned long index, data_not_copied, mmap_len;
380 unsigned char *bufp;
381 unsigned long size, copied_size;
382 int retval = 0, add_to_list = 0;
383 static int sent_offset;
384 static unsigned long sent_index;
386 stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
387 if (!stream_bufs)
388 return -ENOMEM;
389 stream_bufs->addr = sst_drv_ctx->mmap_mem;
390 #ifdef CONFIG_MRST_RAR_HANDLER
391 if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
392 for (index = stream->sg_index; index < nr_segs; index++) {
393 __u32 rar_handle;
394 struct sst_stream_bufs *stream_bufs =
395 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
397 stream->sg_index = index;
398 if (!stream_bufs)
399 return -ENOMEM;
400 retval = copy_from_user((void *) &rar_handle,
401 iovec[index].iov_base,
402 sizeof(__u32));
403 if (retval != 0)
404 return -EFAULT;
405 stream_bufs->addr = (char *)rar_handle;
406 stream_bufs->in_use = false;
407 stream_bufs->size = iovec[0].iov_len;
408 /* locking here */
409 mutex_lock(&stream->lock);
410 list_add_tail(&stream_bufs->node, &stream->bufs);
411 mutex_unlock(&stream->lock);
413 stream->sg_index = index;
414 return retval;
416 #endif
417 mmap_len = sst_drv_ctx->mmap_len;
418 stream_bufs->addr = sst_drv_ctx->mmap_mem;
419 bufp = stream->cur_ptr;
421 copied_size = 0;
423 if (!stream->sg_index)
424 sent_index = sent_offset = 0;
426 for (index = stream->sg_index; index < nr_segs; index++) {
427 stream->sg_index = index;
428 if (!stream->cur_ptr)
429 bufp = iovec[index].iov_base;
431 size = ((unsigned long)iovec[index].iov_base
432 + iovec[index].iov_len) - (unsigned long) bufp;
434 if ((copied_size + size) > mmap_len)
435 size = mmap_len - copied_size;
438 if (stream->ops == STREAM_OPS_PLAYBACK) {
439 data_not_copied = copy_from_user(
440 (void *)(stream_bufs->addr + copied_size),
441 bufp, size);
442 if (data_not_copied > 0) {
443 /* Clean up the list and return error code */
444 retval = -EFAULT;
445 break;
447 } else if (stream->ops == STREAM_OPS_CAPTURE) {
448 struct snd_sst_user_cap_list *entry =
449 kzalloc(sizeof(*entry), GFP_KERNEL);
451 if (!entry) {
452 kfree(stream_bufs);
453 return -ENOMEM;
455 entry->iov_index = index;
456 entry->iov_offset = (unsigned long) bufp -
457 (unsigned long)iovec[index].iov_base;
458 entry->offset = copied_size;
459 entry->size = size;
460 list_add_tail(&entry->node, copy_to_list);
463 stream->cur_ptr = bufp + size;
465 if (((unsigned long)iovec[index].iov_base
466 + iovec[index].iov_len) <
467 ((unsigned long)iovec[index].iov_base)) {
468 pr_debug("sst: Buffer overflows");
469 kfree(stream_bufs);
470 return -EINVAL;
473 if (((unsigned long)iovec[index].iov_base
474 + iovec[index].iov_len) ==
475 (unsigned long)stream->cur_ptr) {
476 stream->cur_ptr = NULL;
477 stream->sg_index++;
480 copied_size += size;
481 pr_debug("sst: copied_size - %lx\n", copied_size);
482 if ((copied_size >= mmap_len) ||
483 (stream->sg_index == nr_segs)) {
484 add_to_list = 1;
487 if (add_to_list) {
488 stream_bufs->in_use = false;
489 stream_bufs->size = copied_size;
490 /* locking here */
491 mutex_lock(&stream->lock);
492 list_add_tail(&stream_bufs->node, &stream->bufs);
493 mutex_unlock(&stream->lock);
494 break;
497 return retval;
500 /* This function copies the captured data returned from SST DSP engine
501 * to the user buffers*/
502 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
503 const struct iovec *iovec,
504 struct list_head *copy_to_list)
506 struct snd_sst_user_cap_list *entry, *_entry;
507 struct sst_stream_bufs *kbufs = NULL, *_kbufs;
508 int retval = 0;
509 unsigned long data_not_copied;
511 /* copy sent buffers */
512 pr_debug("sst: capture stream copying to user now...\n");
513 list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
514 if (kbufs->in_use == true) {
515 /* copy to user */
516 list_for_each_entry_safe(entry, _entry,
517 copy_to_list, node) {
518 data_not_copied = copy_to_user((void *)
519 iovec[entry->iov_index].iov_base +
520 entry->iov_offset,
521 kbufs->addr + entry->offset,
522 entry->size);
523 if (data_not_copied > 0) {
524 /* Clean up the list and return error */
525 retval = -EFAULT;
526 break;
528 list_del(&entry->node);
529 kfree(entry);
533 pr_debug("sst: end of cap copy\n");
534 return retval;
538 * snd_sst_userbufs_play_cap - constructs the list from user buffers
540 * @iovec:pointer to iovec structure
541 * @nr_segs:number entries in the iovec structure
542 * @str_id:stream id
543 * @stream:pointer to stream_info structure
545 * This function will traverse the user list and copy the data to the kernel
546 * space buffers.
548 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
549 unsigned long nr_segs, unsigned int str_id,
550 struct stream_info *stream)
552 int retval;
553 LIST_HEAD(copy_to_list);
556 retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
557 &copy_to_list);
559 retval = intel_sst_play_capture(stream, str_id);
560 if (retval < 0)
561 return retval;
563 if (stream->ops == STREAM_OPS_CAPTURE) {
564 retval = snd_sst_copy_userbuf_capture(stream, iovec,
565 &copy_to_list);
567 return retval;
570 /* This function is common function across read/write
571 for user buffers called from system calls*/
572 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
573 size_t count)
575 int retval;
576 struct stream_info *stream;
577 struct iovec iovec;
578 unsigned long nr_segs;
580 retval = sst_validate_strid(str_id);
581 if (retval)
582 return -EINVAL;
583 stream = &sst_drv_ctx->streams[str_id];
584 if (stream->mmapped == true) {
585 pr_warn("sst: user write and stream is mapped");
586 return -EIO;
588 if (!count)
589 return -EINVAL;
590 stream->curr_bytes = 0;
591 stream->cumm_bytes = 0;
592 /* copy user buf details */
593 pr_debug("sst: new buffers %p, copy size %d, status %d\n" ,
594 buf, (int) count, (int) stream->status);
596 stream->buf_type = SST_BUF_USER_STATIC;
597 iovec.iov_base = (void *)buf;
598 iovec.iov_len = count;
599 nr_segs = 1;
601 do {
602 retval = snd_sst_userbufs_play_cap(
603 &iovec, nr_segs, str_id, stream);
604 if (retval < 0)
605 break;
607 } while (stream->sg_index < nr_segs);
609 stream->sg_index = 0;
610 stream->cur_ptr = NULL;
611 if (retval >= 0)
612 retval = stream->cumm_bytes;
613 pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
614 return retval;
617 /***
618 * intel_sst_write - This function is called when user tries to play out data
620 * @file_ptr:pointer to file
621 * @buf:user buffer to be played out
622 * @count:size of tthe buffer
623 * @offset:offset to start from
625 * writes the encoded data into DSP
627 int intel_sst_write(struct file *file_ptr, const char __user *buf,
628 size_t count, loff_t *offset)
630 struct ioctl_pvt_data *data = file_ptr->private_data;
631 int str_id = data->str_id;
632 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
634 pr_debug("sst: called for %d\n", str_id);
635 if (stream->status == STREAM_UN_INIT ||
636 stream->status == STREAM_DECODE) {
637 return -EBADRQC;
639 return intel_sst_read_write(str_id, (char __user *)buf, count);
643 * intel_sst_aio_write - write buffers
645 * @kiocb:pointer to a structure containing file pointer
646 * @iov:list of user buffer to be played out
647 * @nr_segs:number of entries
648 * @offset:offset to start from
650 * This function is called when user tries to play out multiple data buffers
652 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
653 unsigned long nr_segs, loff_t offset)
655 int retval;
656 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
657 int str_id = data->str_id;
658 struct stream_info *stream;
660 pr_debug("sst: entry - %ld\n", nr_segs);
662 if (is_sync_kiocb(kiocb) == false)
663 return -EINVAL;
665 pr_debug("sst: called for str_id %d\n", str_id);
666 retval = sst_validate_strid(str_id);
667 if (retval)
668 return -EINVAL;
669 stream = &sst_drv_ctx->streams[str_id];
670 if (stream->mmapped == true)
671 return -EIO;
672 if (stream->status == STREAM_UN_INIT ||
673 stream->status == STREAM_DECODE) {
674 return -EBADRQC;
676 stream->curr_bytes = 0;
677 stream->cumm_bytes = 0;
678 pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
679 nr_segs, (int) offset, (int) stream->status);
680 stream->buf_type = SST_BUF_USER_STATIC;
681 do {
682 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
683 str_id, stream);
684 if (retval < 0)
685 break;
687 } while (stream->sg_index < nr_segs);
689 stream->sg_index = 0;
690 stream->cur_ptr = NULL;
691 if (retval >= 0)
692 retval = stream->cumm_bytes;
693 pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
694 return retval;
698 * intel_sst_read - read the encoded data
700 * @file_ptr: pointer to file
701 * @buf: user buffer to be filled with captured data
702 * @count: size of tthe buffer
703 * @offset: offset to start from
705 * This function is called when user tries to capture data
707 int intel_sst_read(struct file *file_ptr, char __user *buf,
708 size_t count, loff_t *offset)
710 struct ioctl_pvt_data *data = file_ptr->private_data;
711 int str_id = data->str_id;
712 struct stream_info *stream = &sst_drv_ctx->streams[str_id];
714 pr_debug("sst: called for %d\n", str_id);
715 if (stream->status == STREAM_UN_INIT ||
716 stream->status == STREAM_DECODE)
717 return -EBADRQC;
718 return intel_sst_read_write(str_id, buf, count);
722 * intel_sst_aio_read - aio read
724 * @kiocb: pointer to a structure containing file pointer
725 * @iov: list of user buffer to be filled with captured
726 * @nr_segs: number of entries
727 * @offset: offset to start from
729 * This function is called when user tries to capture out multiple data buffers
731 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
732 unsigned long nr_segs, loff_t offset)
734 int retval;
735 struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
736 int str_id = data->str_id;
737 struct stream_info *stream;
739 pr_debug("sst: entry - %ld\n", nr_segs);
741 if (is_sync_kiocb(kiocb) == false) {
742 pr_debug("sst: aio_read from user space is not allowed\n");
743 return -EINVAL;
746 pr_debug("sst: called for str_id %d\n", str_id);
747 retval = sst_validate_strid(str_id);
748 if (retval)
749 return -EINVAL;
750 stream = &sst_drv_ctx->streams[str_id];
751 if (stream->mmapped == true)
752 return -EIO;
753 if (stream->status == STREAM_UN_INIT ||
754 stream->status == STREAM_DECODE)
755 return -EBADRQC;
756 stream->curr_bytes = 0;
757 stream->cumm_bytes = 0;
759 pr_debug("sst: new segs %ld, offset %d, status %d\n" ,
760 nr_segs, (int) offset, (int) stream->status);
761 stream->buf_type = SST_BUF_USER_STATIC;
762 do {
763 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
764 str_id, stream);
765 if (retval < 0)
766 break;
768 } while (stream->sg_index < nr_segs);
770 stream->sg_index = 0;
771 stream->cur_ptr = NULL;
772 if (retval >= 0)
773 retval = stream->cumm_bytes;
774 pr_debug("sst: end of play/rec bytes = %d!!\n", retval);
775 return retval;
778 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
779 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
781 pr_debug("sst: codec params:result =%d\n",
782 get_prm->codec_params.result);
783 pr_debug("sst: codec params:stream = %d\n",
784 get_prm->codec_params.stream_id);
785 pr_debug("sst: codec params:codec = %d\n",
786 get_prm->codec_params.codec);
787 pr_debug("sst: codec params:ops = %d\n",
788 get_prm->codec_params.ops);
789 pr_debug("sst: codec params:stream_type= %d\n",
790 get_prm->codec_params.stream_type);
791 pr_debug("sst: pcmparams:sfreq= %d\n",
792 get_prm->pcm_params.sfreq);
793 pr_debug("sst: pcmparams:num_chan= %d\n",
794 get_prm->pcm_params.num_chan);
795 pr_debug("sst: pcmparams:pcm_wd_sz= %d\n",
796 get_prm->pcm_params.pcm_wd_sz);
797 return;
801 * intel_sst_ioctl - recieves the device ioctl's
802 * @file_ptr:pointer to file
803 * @cmd:Ioctl cmd
804 * @arg:data
806 * This function is called by OS when a user space component
807 * sends an Ioctl to SST driver
809 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
811 int retval = 0;
812 struct ioctl_pvt_data *data = NULL;
813 int str_id = 0, minor = 0;
815 data = file_ptr->private_data;
816 if (data) {
817 minor = 0;
818 str_id = data->str_id;
819 } else
820 minor = 1;
822 if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
823 return -EBUSY;
825 switch (_IOC_NR(cmd)) {
826 case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
827 pr_debug("sst: IOCTL_PAUSE recieved for %d!\n", str_id);
828 if (minor != STREAM_MODULE) {
829 retval = -EBADRQC;
830 break;
832 retval = sst_pause_stream(str_id);
833 break;
835 case _IOC_NR(SNDRV_SST_STREAM_RESUME):
836 pr_debug("sst: SNDRV_SST_IOCTL_RESUME recieved!\n");
837 if (minor != STREAM_MODULE) {
838 retval = -EBADRQC;
839 break;
841 retval = sst_resume_stream(str_id);
842 break;
844 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
845 struct snd_sst_params *str_param = (struct snd_sst_params *)arg;
847 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n");
848 if (minor != STREAM_MODULE) {
849 retval = -EBADRQC;
850 break;
853 if (!str_id) {
855 retval = sst_get_stream(str_param);
856 if (retval > 0) {
857 struct stream_info *str_info;
858 sst_drv_ctx->stream_cnt++;
859 data->str_id = retval;
860 str_info = &sst_drv_ctx->streams[retval];
861 str_info->src = SST_DRV;
862 retval = copy_to_user(&str_param->stream_id,
863 &retval, sizeof(__u32));
864 if (retval)
865 retval = -EFAULT;
866 } else {
867 if (retval == -SST_ERR_INVALID_PARAMS)
868 retval = -EINVAL;
870 } else {
871 pr_debug("sst: SET_STREAM_PARAMS recieved!\n");
872 /* allocated set params only */
873 retval = sst_set_stream_param(str_id, str_param);
874 /* Block the call for reply */
875 if (!retval) {
876 int sfreq = 0, word_size = 0, num_channel = 0;
877 sfreq = str_param->sparams.uc.pcm_params.sfreq;
878 word_size = str_param->sparams.
879 uc.pcm_params.pcm_wd_sz;
880 num_channel = str_param->
881 sparams.uc.pcm_params.num_chan;
882 if (str_param->ops == STREAM_OPS_CAPTURE) {
883 sst_drv_ctx->scard_ops->\
884 set_pcm_audio_params(sfreq,
885 word_size, num_channel);
889 break;
891 case _IOC_NR(SNDRV_SST_SET_VOL): {
892 struct snd_sst_vol *set_vol;
893 struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg;
894 pr_debug("sst: SET_VOLUME recieved for %d!\n",
895 rec_vol->stream_id);
896 if (minor == STREAM_MODULE && rec_vol->stream_id == 0) {
897 pr_debug("sst: invalid operation!\n");
898 retval = -EPERM;
899 break;
901 set_vol = kzalloc(sizeof(*set_vol), GFP_ATOMIC);
902 if (!set_vol) {
903 pr_debug("sst: mem allocation failed\n");
904 retval = -ENOMEM;
905 break;
907 retval = copy_from_user(set_vol, rec_vol, sizeof(*set_vol));
908 if (retval) {
909 pr_debug("sst: copy failed\n");
910 retval = -EAGAIN;
911 break;
913 retval = sst_set_vol(set_vol);
914 kfree(set_vol);
915 break;
917 case _IOC_NR(SNDRV_SST_GET_VOL): {
918 struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg;
919 struct snd_sst_vol get_vol;
920 pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n",
921 rec_vol->stream_id);
922 if (minor == STREAM_MODULE && rec_vol->stream_id == 0) {
923 pr_debug("sst: invalid operation!\n");
924 retval = -EPERM;
925 break;
927 get_vol.stream_id = rec_vol->stream_id;
928 retval = sst_get_vol(&get_vol);
929 if (retval) {
930 retval = -EIO;
931 break;
933 pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
934 get_vol.stream_id, get_vol.volume,
935 get_vol.ramp_duration, get_vol.ramp_type);
936 retval = copy_to_user((struct snd_sst_vol *)arg,
937 &get_vol, sizeof(get_vol));
938 if (retval) {
939 retval = -EFAULT;
940 break;
942 /*sst_print_get_vol_info(str_id, &get_vol);*/
943 break;
946 case _IOC_NR(SNDRV_SST_MUTE): {
947 struct snd_sst_mute *set_mute;
948 struct snd_sst_vol *rec_mute = (struct snd_sst_vol *)arg;
949 pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n",
950 rec_mute->stream_id);
951 if (minor == STREAM_MODULE && rec_mute->stream_id == 0) {
952 retval = -EPERM;
953 break;
955 set_mute = kzalloc(sizeof(*set_mute), GFP_ATOMIC);
956 if (!set_mute) {
957 retval = -ENOMEM;
958 break;
960 retval = copy_from_user(set_mute, rec_mute, sizeof(*set_mute));
961 if (retval) {
962 retval = -EFAULT;
963 break;
965 retval = sst_set_mute(set_mute);
966 kfree(set_mute);
967 break;
969 case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
970 struct snd_sst_get_stream_params get_params;
972 pr_debug("sst: IOCTL_GET_PARAMS recieved!\n");
973 if (minor != 0) {
974 retval = -EBADRQC;
975 break;
978 retval = sst_get_stream_params(str_id, &get_params);
979 if (retval) {
980 retval = -EIO;
981 break;
983 retval = copy_to_user((struct snd_sst_get_stream_params *)arg,
984 &get_params, sizeof(get_params));
985 if (retval) {
986 retval = -EBUSY;
987 break;
989 sst_print_stream_params(&get_params);
990 break;
993 case _IOC_NR(SNDRV_SST_MMAP_PLAY):
994 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE):
995 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n");
996 if (minor != STREAM_MODULE) {
997 retval = -EBADRQC;
998 break;
1000 retval = intel_sst_mmap_play_capture(str_id,
1001 (struct snd_sst_mmap_buffs *)arg);
1002 break;
1004 case _IOC_NR(SNDRV_SST_STREAM_DROP):
1005 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n");
1006 if (minor != STREAM_MODULE) {
1007 retval = -EINVAL;
1008 break;
1010 retval = sst_drop_stream(str_id);
1011 break;
1013 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1014 unsigned long long *ms = (unsigned long long *)arg;
1015 struct snd_sst_tstamp tstamp = {0};
1016 unsigned long long time, freq, mod;
1018 pr_debug("sst: SNDRV_SST_STREAM_GET_TSTAMP recieved!\n");
1019 if (minor != STREAM_MODULE) {
1020 retval = -EBADRQC;
1021 break;
1023 memcpy_fromio(&tstamp,
1024 ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1025 +(str_id * sizeof(tstamp))),
1026 sizeof(tstamp));
1027 time = tstamp.samples_rendered;
1028 freq = (unsigned long long) tstamp.sampling_frequency;
1029 time = time * 1000; /* converting it to ms */
1030 mod = do_div(time, freq);
1031 retval = copy_to_user(ms, &time, sizeof(*ms));
1032 if (retval)
1033 retval = -EFAULT;
1034 break;
1037 case _IOC_NR(SNDRV_SST_STREAM_START):{
1038 struct stream_info *stream;
1040 pr_debug("sst: SNDRV_SST_STREAM_START recieved!\n");
1041 if (minor != STREAM_MODULE) {
1042 retval = -EINVAL;
1043 break;
1045 retval = sst_validate_strid(str_id);
1046 if (retval)
1047 break;
1048 stream = &sst_drv_ctx->streams[str_id];
1049 mutex_lock(&stream->lock);
1050 if (stream->status == STREAM_INIT &&
1051 stream->need_draining != true) {
1052 stream->prev = stream->status;
1053 stream->status = STREAM_RUNNING;
1054 if (stream->ops == STREAM_OPS_PLAYBACK ||
1055 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1056 retval = sst_play_frame(str_id);
1057 } else if (stream->ops == STREAM_OPS_CAPTURE)
1058 retval = sst_capture_frame(str_id);
1059 else {
1060 retval = -EINVAL;
1061 mutex_unlock(&stream->lock);
1062 break;
1064 if (retval < 0) {
1065 stream->status = STREAM_INIT;
1066 mutex_unlock(&stream->lock);
1067 break;
1069 } else {
1070 retval = -EINVAL;
1072 mutex_unlock(&stream->lock);
1073 break;
1076 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1077 struct snd_sst_target_device *target_device;
1079 pr_debug("sst: SET_TARGET_DEVICE recieved!\n");
1080 target_device = (struct snd_sst_target_device *)arg;
1081 BUG_ON(!target_device);
1082 if (minor != AM_MODULE) {
1083 retval = -EBADRQC;
1084 break;
1086 retval = sst_target_device_select(target_device);
1087 break;
1090 case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1091 struct snd_sst_driver_info *info =
1092 (struct snd_sst_driver_info *)arg;
1094 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n");
1095 info->version = SST_VERSION_NUM;
1096 /* hard coding, shud get sumhow later */
1097 info->active_pcm_streams = sst_drv_ctx->stream_cnt -
1098 sst_drv_ctx->encoded_cnt;
1099 info->active_enc_streams = sst_drv_ctx->encoded_cnt;
1100 info->max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1101 info->max_enc_streams = MAX_ENC_STREAM;
1102 info->buf_per_stream = sst_drv_ctx->mmap_len;
1103 break;
1106 case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1107 struct snd_sst_dbufs *param =
1108 (struct snd_sst_dbufs *)arg, dbufs_local;
1109 int i;
1110 struct snd_sst_buffs ibufs, obufs;
1111 struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries],
1112 obuf_temp[param->obufs->entries];
1114 pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n");
1115 if (minor != STREAM_MODULE) {
1116 retval = -EBADRQC;
1117 break;
1119 if (!param) {
1120 retval = -EINVAL;
1121 break;
1124 dbufs_local.input_bytes_consumed = param->input_bytes_consumed;
1125 dbufs_local.output_bytes_produced =
1126 param->output_bytes_produced;
1127 dbufs_local.ibufs = &ibufs;
1128 dbufs_local.obufs = &obufs;
1129 dbufs_local.ibufs->entries = param->ibufs->entries;
1130 dbufs_local.ibufs->type = param->ibufs->type;
1131 dbufs_local.obufs->entries = param->obufs->entries;
1132 dbufs_local.obufs->type = param->obufs->type;
1134 dbufs_local.ibufs->buff_entry = ibuf_temp;
1135 for (i = 0; i < dbufs_local.ibufs->entries; i++) {
1136 ibuf_temp[i].buffer =
1137 param->ibufs->buff_entry[i].buffer;
1138 ibuf_temp[i].size =
1139 param->ibufs->buff_entry[i].size;
1141 dbufs_local.obufs->buff_entry = obuf_temp;
1142 for (i = 0; i < dbufs_local.obufs->entries; i++) {
1143 obuf_temp[i].buffer =
1144 param->obufs->buff_entry[i].buffer;
1145 obuf_temp[i].size =
1146 param->obufs->buff_entry[i].size;
1148 retval = sst_decode(str_id, &dbufs_local);
1149 if (retval)
1150 retval = -EAGAIN;
1151 retval = copy_to_user(&param->input_bytes_consumed,
1152 &dbufs_local.input_bytes_consumed,
1153 sizeof(unsigned long long));
1154 if (retval) {
1155 retval = -EFAULT;
1156 break;
1158 retval = copy_to_user(&param->output_bytes_produced,
1159 &dbufs_local.output_bytes_produced,
1160 sizeof(unsigned long long));
1161 if (retval) {
1162 retval = -EFAULT;
1163 break;
1165 break;
1168 case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1169 pr_debug("sst: SNDRV_SST_STREAM_DRAIN recived\n");
1170 if (minor != STREAM_MODULE) {
1171 retval = -EINVAL;
1172 break;
1174 retval = sst_drain_stream(str_id);
1175 break;
1177 case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1178 unsigned long long *bytes = (unsigned long long *)arg;
1179 struct snd_sst_tstamp tstamp = {0};
1181 pr_debug("sst: STREAM_BYTES_DECODED recieved!\n");
1182 if (minor != STREAM_MODULE) {
1183 retval = -EINVAL;
1184 break;
1186 memcpy_fromio(&tstamp,
1187 ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
1188 +(str_id * sizeof(tstamp))),
1189 sizeof(tstamp));
1190 retval = copy_to_user(bytes, &tstamp.bytes_processed,
1191 sizeof(*bytes));
1192 if (retval)
1193 retval = -EFAULT;
1194 break;
1196 case _IOC_NR(SNDRV_SST_FW_INFO): {
1197 struct snd_sst_fw_info *fw_info;
1199 pr_debug("sst: SNDRV_SST_FW_INFO recived\n");
1201 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1202 if (!fw_info) {
1203 retval = -ENOMEM;
1204 break;
1206 retval = sst_get_fw_info(fw_info);
1207 if (retval) {
1208 retval = -EIO;
1209 kfree(fw_info);
1210 break;
1212 retval = copy_to_user((struct snd_sst_dbufs *)arg,
1213 fw_info, sizeof(*fw_info));
1214 if (retval) {
1215 kfree(fw_info);
1216 retval = -EFAULT;
1217 break;
1219 /*sst_print_fw_info(fw_info);*/
1220 kfree(fw_info);
1221 break;
1223 default:
1224 retval = -EINVAL;
1226 pr_debug("sst: intel_sst_ioctl:complete ret code = %d\n", retval);
1227 return retval;