Merge branch 'fixes-modulesplit' into fixes
[pandora-kernel.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
1 /*
2  *  intel_sst_interface.c - Intel SST Driver for audio engine
3  *
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  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10  *
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.
14  *
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.
19  *
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.
23  *
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
28  */
29
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
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 #ifdef CONFIG_MRST_RAR_HANDLER
41 #include <linux/rar_register.h>
42 #include "../../../drivers/staging/memrar/memrar.h"
43 #endif
44 #include "intel_sst.h"
45 #include "intel_sst_ioctl.h"
46 #include "intel_sst_fw_ipc.h"
47 #include "intel_sst_common.h"
48
49 #define AM_MODULE 1
50 #define STREAM_MODULE 0
51
52
53 /**
54 * intel_sst_check_device - checks SST device
55 *
56 * This utility function checks the state of SST device and downlaods FW if
57 * not done, or resumes the device if suspended
58 */
59
60 static int intel_sst_check_device(void)
61 {
62         int retval = 0;
63         if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
64                 pr_warn("Sound card not available\n");
65                 return -EIO;
66         }
67         if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
68                 pr_debug("Resuming from Suspended state\n");
69                 retval = intel_sst_resume(sst_drv_ctx->pci);
70                 if (retval) {
71                         pr_debug("Resume Failed= %#x,abort\n", retval);
72                         return retval;
73                 }
74         }
75
76         if (sst_drv_ctx->sst_state == SST_UN_INIT) {
77                 /* FW is not downloaded */
78                 retval = sst_download_fw();
79                 if (retval)
80                         return -ENODEV;
81                 if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
82                         retval = sst_drv_ctx->rx_time_slot_status;
83                         if (retval != RX_TIMESLOT_UNINIT
84                                         && sst_drv_ctx->pmic_vendor != SND_NC)
85                                 sst_enable_rx_timeslot(retval);
86                 }
87         }
88         return 0;
89 }
90
91 /**
92  * intel_sst_open - opens a handle to driver
93  *
94  * @i_node:     inode structure
95  * @file_ptr:pointer to file
96  *
97  * This function is called by OS when a user space component
98  * tries to get a driver handle. Only one handle at a time
99  * will be allowed
100  */
101 int intel_sst_open(struct inode *i_node, struct file *file_ptr)
102 {
103         unsigned int retval;
104
105         mutex_lock(&sst_drv_ctx->stream_lock);
106         pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
107         retval = intel_sst_check_device();
108         if (retval) {
109                 pm_runtime_put(&sst_drv_ctx->pci->dev);
110                 mutex_unlock(&sst_drv_ctx->stream_lock);
111                 return retval;
112         }
113
114         if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
115                 struct ioctl_pvt_data *data =
116                         kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
117                 if (!data) {
118                         pm_runtime_put(&sst_drv_ctx->pci->dev);
119                         mutex_unlock(&sst_drv_ctx->stream_lock);
120                         return -ENOMEM;
121                 }
122
123                 sst_drv_ctx->encoded_cnt++;
124                 mutex_unlock(&sst_drv_ctx->stream_lock);
125                 data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
126                 data->str_id = 0;
127                 file_ptr->private_data = (void *)data;
128                 pr_debug("pvt_id handle = %d!\n", data->pvt_id);
129         } else {
130                 retval = -EUSERS;
131                 pm_runtime_put(&sst_drv_ctx->pci->dev);
132                 mutex_unlock(&sst_drv_ctx->stream_lock);
133         }
134         return retval;
135 }
136
137 /**
138  * intel_sst_open_cntrl - opens a handle to driver
139  *
140  * @i_node:     inode structure
141  * @file_ptr:pointer to file
142  *
143  * This function is called by OS when a user space component
144  * tries to get a driver handle to /dev/intel_sst_control.
145  * Only one handle at a time will be allowed
146  * This is for control operations only
147  */
148 int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
149 {
150         unsigned int retval;
151
152         /* audio manager open */
153         mutex_lock(&sst_drv_ctx->stream_lock);
154         pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
155         retval = intel_sst_check_device();
156         if (retval) {
157                 pm_runtime_put(&sst_drv_ctx->pci->dev);
158                 mutex_unlock(&sst_drv_ctx->stream_lock);
159                 return retval;
160         }
161
162         if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
163                 sst_drv_ctx->am_cnt++;
164                 pr_debug("AM handle opened...\n");
165                 file_ptr->private_data = NULL;
166         } else {
167                 retval = -EACCES;
168                 pm_runtime_put(&sst_drv_ctx->pci->dev);
169         }
170
171         mutex_unlock(&sst_drv_ctx->stream_lock);
172         return retval;
173 }
174
175 /**
176  * intel_sst_release - releases a handle to driver
177  *
178  * @i_node:     inode structure
179  * @file_ptr:   pointer to file
180  *
181  * This function is called by OS when a user space component
182  * tries to release a driver handle.
183  */
184 int intel_sst_release(struct inode *i_node, struct file *file_ptr)
185 {
186         struct ioctl_pvt_data *data = file_ptr->private_data;
187
188         pr_debug("Release called, closing app handle\n");
189         mutex_lock(&sst_drv_ctx->stream_lock);
190         sst_drv_ctx->encoded_cnt--;
191         sst_drv_ctx->stream_cnt--;
192         pm_runtime_put(&sst_drv_ctx->pci->dev);
193         mutex_unlock(&sst_drv_ctx->stream_lock);
194         free_stream_context(data->str_id);
195         kfree(data);
196         return 0;
197 }
198
199 int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
200 {
201         /* audio manager close */
202         mutex_lock(&sst_drv_ctx->stream_lock);
203         sst_drv_ctx->am_cnt--;
204         pm_runtime_put(&sst_drv_ctx->pci->dev);
205         mutex_unlock(&sst_drv_ctx->stream_lock);
206         pr_debug("AM handle closed\n");
207         return 0;
208 }
209
210 /**
211 * intel_sst_mmap - mmaps a kernel buffer to user space for copying data
212 *
213 * @vma:         vm area structure instance
214 * @file_ptr:    pointer to file
215 *
216 * This function is called by OS when a user space component
217 * tries to get mmap memory from driver
218 */
219 int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
220 {
221         int retval, length;
222         struct ioctl_pvt_data *data =
223                 (struct ioctl_pvt_data *)file_ptr->private_data;
224         int str_id = data->str_id;
225         void *mem_area;
226
227         retval = sst_validate_strid(str_id);
228         if (retval)
229                 return -EINVAL;
230
231         length = vma->vm_end - vma->vm_start;
232         pr_debug("called for stream %d length 0x%x\n", str_id, length);
233
234         if (length > sst_drv_ctx->mmap_len)
235                 return -ENOMEM;
236         if (!sst_drv_ctx->mmap_mem)
237                 return -EIO;
238
239         /* round it up to the page boundary  */
240         /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
241                                 + PAGE_SIZE - 1) & PAGE_MASK);*/
242         mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
243
244         /* map the whole physically contiguous area in one piece  */
245         retval = remap_pfn_range(vma,
246                         vma->vm_start,
247                         virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
248                         length,
249                         vma->vm_page_prot);
250         if (retval)
251                 sst_drv_ctx->streams[str_id].mmapped = false;
252         else
253                 sst_drv_ctx->streams[str_id].mmapped = true;
254
255         pr_debug("mmap ret 0x%x\n", retval);
256         return retval;
257 }
258
259 /* sets mmap data buffers to play/capture*/
260 static int intel_sst_mmap_play_capture(u32 str_id,
261                 struct snd_sst_mmap_buffs *mmap_buf)
262 {
263         struct sst_stream_bufs *bufs;
264         int retval, i;
265         struct stream_info *stream;
266         struct snd_sst_mmap_buff_entry *buf_entry;
267         struct snd_sst_mmap_buff_entry *tmp_buf;
268
269         pr_debug("called for str_id %d\n", str_id);
270         retval = sst_validate_strid(str_id);
271         if (retval)
272                 return -EINVAL;
273
274         stream = &sst_drv_ctx->streams[str_id];
275         if (stream->mmapped != true)
276                 return -EIO;
277
278         if (stream->status == STREAM_UN_INIT ||
279                 stream->status == STREAM_DECODE) {
280                 return -EBADRQC;
281         }
282         stream->curr_bytes = 0;
283         stream->cumm_bytes = 0;
284
285         tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
286         if (!tmp_buf)
287                 return -ENOMEM;
288         if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
289                         mmap_buf->entries * sizeof(*tmp_buf))) {
290                 retval = -EFAULT;
291                 goto out_free;
292         }
293
294         pr_debug("new buffers count %d status %d\n",
295                         mmap_buf->entries, stream->status);
296         buf_entry = tmp_buf;
297         for (i = 0; i < mmap_buf->entries; i++) {
298                 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
299                 if (!bufs) {
300                         retval = -ENOMEM;
301                         goto out_free;
302                 }
303                 bufs->size = buf_entry->size;
304                 bufs->offset = buf_entry->offset;
305                 bufs->addr = sst_drv_ctx->mmap_mem;
306                 bufs->in_use = false;
307                 buf_entry++;
308                 /* locking here */
309                 mutex_lock(&stream->lock);
310                 list_add_tail(&bufs->node, &stream->bufs);
311                 mutex_unlock(&stream->lock);
312         }
313
314         mutex_lock(&stream->lock);
315         stream->data_blk.condition = false;
316         stream->data_blk.ret_code = 0;
317         if (stream->status == STREAM_INIT &&
318                         stream->prev != STREAM_UN_INIT &&
319                         stream->need_draining != true) {
320                 stream->prev = stream->status;
321                 stream->status = STREAM_RUNNING;
322                 if (stream->ops == STREAM_OPS_PLAYBACK) {
323                         if (sst_play_frame(str_id) < 0) {
324                                 pr_warn("play frames fail\n");
325                                 mutex_unlock(&stream->lock);
326                                 retval = -EIO;
327                                 goto out_free;
328                         }
329                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
330                         if (sst_capture_frame(str_id) < 0) {
331                                 pr_warn("capture frame fail\n");
332                                 mutex_unlock(&stream->lock);
333                                 retval = -EIO;
334                                 goto out_free;
335                         }
336                 }
337         }
338         mutex_unlock(&stream->lock);
339         /* Block the call for reply */
340         if (!list_empty(&stream->bufs)) {
341                 stream->data_blk.on = true;
342                 retval = sst_wait_interruptible(sst_drv_ctx,
343                                         &stream->data_blk);
344         }
345
346         if (retval >= 0)
347                 retval = stream->cumm_bytes;
348         pr_debug("end of play/rec ioctl bytes = %d!!\n", retval);
349
350 out_free:
351         kfree(tmp_buf);
352         return retval;
353 }
354
355 /*sets user data buffers to play/capture*/
356 static int intel_sst_play_capture(struct stream_info *stream, int str_id)
357 {
358         int retval;
359
360         stream->data_blk.ret_code = 0;
361         stream->data_blk.on = true;
362         stream->data_blk.condition = false;
363
364         mutex_lock(&stream->lock);
365         if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
366                 /* stream is started */
367                 stream->prev = stream->status;
368                 stream->status = STREAM_RUNNING;
369         }
370
371         if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
372                 /* stream is not started yet */
373                 pr_debug("Stream isn't in started state %d, prev %d\n",
374                         stream->status, stream->prev);
375         } else if ((stream->status == STREAM_RUNNING ||
376                         stream->status == STREAM_PAUSED) &&
377                         stream->need_draining != true) {
378                 /* stream is started */
379                 if (stream->ops == STREAM_OPS_PLAYBACK ||
380                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
381                         if (sst_play_frame(str_id) < 0) {
382                                 pr_warn("play frames failed\n");
383                                 mutex_unlock(&stream->lock);
384                                 return -EIO;
385                         }
386                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
387                         if (sst_capture_frame(str_id) < 0) {
388                                 pr_warn("capture frames failed\n");
389                                 mutex_unlock(&stream->lock);
390                                 return -EIO;
391                         }
392                 }
393         } else {
394                 mutex_unlock(&stream->lock);
395                 return -EIO;
396         }
397         mutex_unlock(&stream->lock);
398         /* Block the call for reply */
399
400         retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
401         if (retval) {
402                 stream->status = STREAM_INIT;
403                 pr_debug("wait returned error...\n");
404         }
405         return retval;
406 }
407
408 /* fills kernel list with buffer addresses for SST DSP driver to process*/
409 static int snd_sst_fill_kernel_list(struct stream_info *stream,
410                         const struct iovec *iovec, unsigned long nr_segs,
411                         struct list_head *copy_to_list)
412 {
413         struct sst_stream_bufs *stream_bufs;
414         unsigned long index, mmap_len;
415         unsigned char __user *bufp;
416         unsigned long size, copied_size;
417         int retval = 0, add_to_list = 0;
418         static int sent_offset;
419         static unsigned long sent_index;
420
421 #ifdef CONFIG_MRST_RAR_HANDLER
422         if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
423                 for (index = stream->sg_index; index < nr_segs; index++) {
424                         __u32 rar_handle;
425                         struct sst_stream_bufs *stream_bufs =
426                                 kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
427
428                         stream->sg_index = index;
429                         if (!stream_bufs)
430                                 return -ENOMEM;
431                         if (copy_from_user((void *) &rar_handle,
432                                         iovec[index].iov_base,
433                                         sizeof(__u32))) {
434                                 kfree(stream_bufs);
435                                 return -EFAULT;
436                         }
437                         stream_bufs->addr = (char *)rar_handle;
438                         stream_bufs->in_use = false;
439                         stream_bufs->size = iovec[0].iov_len;
440                         /* locking here */
441                         mutex_lock(&stream->lock);
442                         list_add_tail(&stream_bufs->node, &stream->bufs);
443                         mutex_unlock(&stream->lock);
444                 }
445                 stream->sg_index = index;
446                 return retval;
447         }
448 #endif
449         stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
450         if (!stream_bufs)
451                 return -ENOMEM;
452         stream_bufs->addr = sst_drv_ctx->mmap_mem;
453         mmap_len = sst_drv_ctx->mmap_len;
454         stream_bufs->addr = sst_drv_ctx->mmap_mem;
455         bufp = stream->cur_ptr;
456
457         copied_size = 0;
458
459         if (!stream->sg_index)
460                 sent_index = sent_offset = 0;
461
462         for (index = stream->sg_index; index < nr_segs; index++) {
463                 stream->sg_index = index;
464                 if (!stream->cur_ptr)
465                         bufp = iovec[index].iov_base;
466
467                 size = ((unsigned long)iovec[index].iov_base
468                         + iovec[index].iov_len) - (unsigned long) bufp;
469
470                 if ((copied_size + size) > mmap_len)
471                         size = mmap_len - copied_size;
472
473
474                 if (stream->ops == STREAM_OPS_PLAYBACK) {
475                         if (copy_from_user((void *)
476                                         (stream_bufs->addr + copied_size),
477                                         bufp, size)) {
478                                 /* Clean up the list and return error code */
479                                 retval = -EFAULT;
480                                 break;
481                         }
482                 } else if (stream->ops == STREAM_OPS_CAPTURE) {
483                         struct snd_sst_user_cap_list *entry =
484                                 kzalloc(sizeof(*entry), GFP_KERNEL);
485
486                         if (!entry) {
487                                 kfree(stream_bufs);
488                                 return -ENOMEM;
489                         }
490                         entry->iov_index = index;
491                         entry->iov_offset = (unsigned long) bufp -
492                                         (unsigned long)iovec[index].iov_base;
493                         entry->offset = copied_size;
494                         entry->size = size;
495                         list_add_tail(&entry->node, copy_to_list);
496                 }
497
498                 stream->cur_ptr = bufp + size;
499
500                 if (((unsigned long)iovec[index].iov_base
501                                 + iovec[index].iov_len) <
502                                 ((unsigned long)iovec[index].iov_base)) {
503                         pr_debug("Buffer overflows\n");
504                         kfree(stream_bufs);
505                         return -EINVAL;
506                 }
507
508                 if (((unsigned long)iovec[index].iov_base
509                                         + iovec[index].iov_len) ==
510                                         (unsigned long)stream->cur_ptr) {
511                         stream->cur_ptr = NULL;
512                         stream->sg_index++;
513                 }
514
515                 copied_size += size;
516                 pr_debug("copied_size - %lx\n", copied_size);
517                 if ((copied_size >= mmap_len) ||
518                                 (stream->sg_index == nr_segs)) {
519                         add_to_list = 1;
520                 }
521
522                 if (add_to_list) {
523                         stream_bufs->in_use = false;
524                         stream_bufs->size = copied_size;
525                         /* locking here */
526                         mutex_lock(&stream->lock);
527                         list_add_tail(&stream_bufs->node, &stream->bufs);
528                         mutex_unlock(&stream->lock);
529                         break;
530                 }
531         }
532         return retval;
533 }
534
535 /* This function copies the captured data returned from SST DSP engine
536  * to the user buffers*/
537 static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
538                         const struct iovec *iovec,
539                         struct list_head *copy_to_list)
540 {
541         struct snd_sst_user_cap_list *entry, *_entry;
542         struct sst_stream_bufs *kbufs = NULL, *_kbufs;
543         int retval = 0;
544
545         /* copy sent buffers */
546         pr_debug("capture stream copying to user now...\n");
547         list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
548                 if (kbufs->in_use == true) {
549                         /* copy to user */
550                         list_for_each_entry_safe(entry, _entry,
551                                                 copy_to_list, node) {
552                                 if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
553                                              kbufs->addr + entry->offset,
554                                              entry->size)) {
555                                         /* Clean up the list and return error */
556                                         retval = -EFAULT;
557                                         break;
558                                 }
559                                 list_del(&entry->node);
560                                 kfree(entry);
561                         }
562                 }
563         }
564         pr_debug("end of cap copy\n");
565         return retval;
566 }
567
568 /*
569  * snd_sst_userbufs_play_cap - constructs the list from user buffers
570  *
571  * @iovec:pointer to iovec structure
572  * @nr_segs:number entries in the iovec structure
573  * @str_id:stream id
574  * @stream:pointer to stream_info structure
575  *
576  * This function will traverse the user list and copy the data to the kernel
577  * space buffers.
578  */
579 static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
580                         unsigned long nr_segs, unsigned int str_id,
581                         struct stream_info *stream)
582 {
583         int retval;
584         LIST_HEAD(copy_to_list);
585
586
587         retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
588                        &copy_to_list);
589
590         retval = intel_sst_play_capture(stream, str_id);
591         if (retval < 0)
592                 return retval;
593
594         if (stream->ops == STREAM_OPS_CAPTURE) {
595                 retval = snd_sst_copy_userbuf_capture(stream, iovec,
596                                 &copy_to_list);
597         }
598         return retval;
599 }
600
601 /* This function is common function across read/write
602   for user buffers called from system calls*/
603 static int intel_sst_read_write(unsigned int str_id, char __user *buf,
604                                         size_t count)
605 {
606         int retval;
607         struct stream_info *stream;
608         struct iovec iovec;
609         unsigned long nr_segs;
610
611         retval = sst_validate_strid(str_id);
612         if (retval)
613                 return -EINVAL;
614         stream = &sst_drv_ctx->streams[str_id];
615         if (stream->mmapped == true) {
616                 pr_warn("user write and stream is mapped\n");
617                 return -EIO;
618         }
619         if (!count)
620                 return -EINVAL;
621         stream->curr_bytes = 0;
622         stream->cumm_bytes = 0;
623         /* copy user buf details */
624         pr_debug("new buffers %p, copy size %d, status %d\n" ,
625                         buf, (int) count, (int) stream->status);
626
627         stream->buf_type = SST_BUF_USER_STATIC;
628         iovec.iov_base = buf;
629         iovec.iov_len  = count;
630         nr_segs = 1;
631
632         do {
633                 retval = snd_sst_userbufs_play_cap(
634                                 &iovec, nr_segs, str_id, stream);
635                 if (retval < 0)
636                         break;
637
638         } while (stream->sg_index < nr_segs);
639
640         stream->sg_index = 0;
641         stream->cur_ptr = NULL;
642         if (retval >= 0)
643                 retval = stream->cumm_bytes;
644         pr_debug("end of play/rec bytes = %d!!\n", retval);
645         return retval;
646 }
647
648 /***
649  * intel_sst_write - This function is called when user tries to play out data
650  *
651  * @file_ptr:pointer to file
652  * @buf:user buffer to be played out
653  * @count:size of tthe buffer
654  * @offset:offset to start from
655  *
656  * writes the encoded data into DSP
657  */
658 int intel_sst_write(struct file *file_ptr, const char __user *buf,
659                         size_t count, loff_t *offset)
660 {
661         struct ioctl_pvt_data *data = file_ptr->private_data;
662         int str_id = data->str_id;
663         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
664
665         pr_debug("called for %d\n", str_id);
666         if (stream->status == STREAM_UN_INIT ||
667                 stream->status == STREAM_DECODE) {
668                 return -EBADRQC;
669         }
670         return intel_sst_read_write(str_id, (char __user *)buf, count);
671 }
672
673 /*
674  * intel_sst_aio_write - write buffers
675  *
676  * @kiocb:pointer to a structure containing file pointer
677  * @iov:list of user buffer to be played out
678  * @nr_segs:number of entries
679  * @offset:offset to start from
680  *
681  * This function is called when user tries to play out multiple data buffers
682  */
683 ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
684                         unsigned long nr_segs, loff_t  offset)
685 {
686         int retval;
687         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
688         int str_id = data->str_id;
689         struct stream_info *stream;
690
691         pr_debug("entry - %ld\n", nr_segs);
692
693         if (is_sync_kiocb(kiocb) == false)
694                 return -EINVAL;
695
696         pr_debug("called for str_id %d\n", str_id);
697         retval = sst_validate_strid(str_id);
698         if (retval)
699                 return -EINVAL;
700         stream = &sst_drv_ctx->streams[str_id];
701         if (stream->mmapped == true)
702                 return -EIO;
703         if (stream->status == STREAM_UN_INIT ||
704                 stream->status == STREAM_DECODE) {
705                 return -EBADRQC;
706         }
707         stream->curr_bytes = 0;
708         stream->cumm_bytes = 0;
709         pr_debug("new segs %ld, offset %d, status %d\n" ,
710                         nr_segs, (int) offset, (int) stream->status);
711         stream->buf_type = SST_BUF_USER_STATIC;
712         do {
713                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
714                                                 str_id, stream);
715                 if (retval < 0)
716                         break;
717
718         } while (stream->sg_index < nr_segs);
719
720         stream->sg_index = 0;
721         stream->cur_ptr = NULL;
722         if (retval >= 0)
723                 retval = stream->cumm_bytes;
724         pr_debug("end of play/rec bytes = %d!!\n", retval);
725         return retval;
726 }
727
728 /*
729  * intel_sst_read - read the encoded data
730  *
731  * @file_ptr: pointer to file
732  * @buf: user buffer to be filled with captured data
733  * @count: size of tthe buffer
734  * @offset: offset to start from
735  *
736  * This function is called when user tries to capture data
737  */
738 int intel_sst_read(struct file *file_ptr, char __user *buf,
739                         size_t count, loff_t *offset)
740 {
741         struct ioctl_pvt_data *data = file_ptr->private_data;
742         int str_id = data->str_id;
743         struct stream_info *stream = &sst_drv_ctx->streams[str_id];
744
745         pr_debug("called for %d\n", str_id);
746         if (stream->status == STREAM_UN_INIT ||
747                         stream->status == STREAM_DECODE)
748                 return -EBADRQC;
749         return intel_sst_read_write(str_id, buf, count);
750 }
751
752 /*
753  * intel_sst_aio_read - aio read
754  *
755  * @kiocb: pointer to a structure containing file pointer
756  * @iov: list of user buffer to be filled with captured
757  * @nr_segs: number of entries
758  * @offset: offset to start from
759  *
760  * This function is called when user tries to capture out multiple data buffers
761  */
762 ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
763                          unsigned long nr_segs, loff_t offset)
764 {
765         int retval;
766         struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
767         int str_id = data->str_id;
768         struct stream_info *stream;
769
770         pr_debug("entry - %ld\n", nr_segs);
771
772         if (is_sync_kiocb(kiocb) == false) {
773                 pr_debug("aio_read from user space is not allowed\n");
774                 return -EINVAL;
775         }
776
777         pr_debug("called for str_id %d\n", str_id);
778         retval = sst_validate_strid(str_id);
779         if (retval)
780                 return -EINVAL;
781         stream = &sst_drv_ctx->streams[str_id];
782         if (stream->mmapped == true)
783                 return -EIO;
784         if (stream->status == STREAM_UN_INIT ||
785                         stream->status == STREAM_DECODE)
786                 return -EBADRQC;
787         stream->curr_bytes = 0;
788         stream->cumm_bytes = 0;
789
790         pr_debug("new segs %ld, offset %d, status %d\n" ,
791                         nr_segs, (int) offset, (int) stream->status);
792         stream->buf_type = SST_BUF_USER_STATIC;
793         do {
794                 retval = snd_sst_userbufs_play_cap(iov, nr_segs,
795                                                 str_id, stream);
796                 if (retval < 0)
797                         break;
798
799         } while (stream->sg_index < nr_segs);
800
801         stream->sg_index = 0;
802         stream->cur_ptr = NULL;
803         if (retval >= 0)
804                 retval = stream->cumm_bytes;
805         pr_debug("end of play/rec bytes = %d!!\n", retval);
806         return retval;
807 }
808
809 /* sst_print_stream_params - prints the stream parameters (debug fn)*/
810 static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
811 {
812         pr_debug("codec params:result = %d\n",
813                                 get_prm->codec_params.result);
814         pr_debug("codec params:stream = %d\n",
815                                 get_prm->codec_params.stream_id);
816         pr_debug("codec params:codec = %d\n",
817                                 get_prm->codec_params.codec);
818         pr_debug("codec params:ops = %d\n",
819                                 get_prm->codec_params.ops);
820         pr_debug("codec params:stream_type = %d\n",
821                                 get_prm->codec_params.stream_type);
822         pr_debug("pcmparams:sfreq = %d\n",
823                                 get_prm->pcm_params.sfreq);
824         pr_debug("pcmparams:num_chan = %d\n",
825                                 get_prm->pcm_params.num_chan);
826         pr_debug("pcmparams:pcm_wd_sz = %d\n",
827                                 get_prm->pcm_params.pcm_wd_sz);
828         return;
829 }
830
831 /**
832  * sst_create_algo_ipc - create ipc msg for algorithm parameters
833  *
834  * @algo_params: Algorithm parameters
835  * @msg: post msg pointer
836  *
837  * This function is called to create ipc msg
838  */
839 int sst_create_algo_ipc(struct snd_ppp_params *algo_params,
840                                         struct ipc_post **msg)
841 {
842         if (sst_create_large_msg(msg))
843                 return -ENOMEM;
844         sst_fill_header(&(*msg)->header,
845                         IPC_IA_ALG_PARAMS, 1, algo_params->str_id);
846         (*msg)->header.part.data = sizeof(u32) +
847                         sizeof(*algo_params) + algo_params->size;
848         memcpy((*msg)->mailbox_data, &(*msg)->header, sizeof(u32));
849         memcpy((*msg)->mailbox_data + sizeof(u32),
850                                 algo_params, sizeof(*algo_params));
851         return 0;
852 }
853
854 /**
855  * sst_send_algo_ipc - send ipc msg for algorithm parameters
856  *
857  * @msg: post msg pointer
858  *
859  * This function is called to send ipc msg
860  */
861 int sst_send_algo_ipc(struct ipc_post **msg)
862 {
863         sst_drv_ctx->ppp_params_blk.condition = false;
864         sst_drv_ctx->ppp_params_blk.ret_code = 0;
865         sst_drv_ctx->ppp_params_blk.on = true;
866         sst_drv_ctx->ppp_params_blk.data = NULL;
867         spin_lock(&sst_drv_ctx->list_spin_lock);
868         list_add_tail(&(*msg)->node, &sst_drv_ctx->ipc_dispatch_list);
869         spin_unlock(&sst_drv_ctx->list_spin_lock);
870         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
871         return sst_wait_interruptible_timeout(sst_drv_ctx,
872                         &sst_drv_ctx->ppp_params_blk, SST_BLOCK_TIMEOUT);
873 }
874
875 /**
876  * intel_sst_ioctl_dsp - receives the device ioctl's
877  *
878  * @cmd:Ioctl cmd
879  * @arg:data
880  *
881  * This function is called when a user space component
882  * sends a DSP Ioctl to SST driver
883  */
884 long intel_sst_ioctl_dsp(unsigned int cmd, unsigned long arg)
885 {
886         int retval = 0;
887         struct snd_ppp_params algo_params;
888         struct snd_ppp_params *algo_params_copied;
889         struct ipc_post *msg;
890
891         switch (_IOC_NR(cmd)) {
892         case _IOC_NR(SNDRV_SST_SET_ALGO):
893                 if (copy_from_user(&algo_params, (void __user *)arg,
894                                                         sizeof(algo_params)))
895                         return -EFAULT;
896                 if (algo_params.size > SST_MAILBOX_SIZE)
897                         return -EMSGSIZE;
898
899                 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
900                         algo_params.algo_id, algo_params.str_id,
901                         algo_params.enable, algo_params.size);
902                 retval = sst_create_algo_ipc(&algo_params, &msg);
903                 if (retval)
904                         break;
905                 algo_params.reserved = 0;
906                 if (copy_from_user(msg->mailbox_data + sizeof(algo_params),
907                                 algo_params.params, algo_params.size))
908                         return -EFAULT;
909
910                 retval = sst_send_algo_ipc(&msg);
911                 if (retval) {
912                         pr_debug("Error in sst_set_algo = %d\n", retval);
913                         retval = -EIO;
914                 }
915                 break;
916
917         case _IOC_NR(SNDRV_SST_GET_ALGO):
918                 if (copy_from_user(&algo_params, (void __user *)arg,
919                                                         sizeof(algo_params)))
920                         return -EFAULT;
921                 pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
922                         algo_params.algo_id, algo_params.str_id,
923                         algo_params.enable, algo_params.size);
924                 retval = sst_create_algo_ipc(&algo_params, &msg);
925                 if (retval)
926                         break;
927                 algo_params.reserved = 1;
928                 retval = sst_send_algo_ipc(&msg);
929                 if (retval) {
930                         pr_debug("Error in sst_get_algo = %d\n", retval);
931                         retval = -EIO;
932                         break;
933                 }
934                 algo_params_copied = (struct snd_ppp_params *)
935                                         sst_drv_ctx->ppp_params_blk.data;
936                 if (algo_params_copied->size > algo_params.size) {
937                         pr_debug("mem insufficient to copy\n");
938                         retval = -EMSGSIZE;
939                         goto free_mem;
940                 } else {
941                         char __user *tmp;
942
943                         if (copy_to_user(algo_params.params,
944                                         algo_params_copied->params,
945                                         algo_params_copied->size)) {
946                                 retval = -EFAULT;
947                                 goto free_mem;
948                         }
949                         tmp = (char __user *)arg + offsetof(
950                                         struct snd_ppp_params, size);
951                         if (copy_to_user(tmp, &algo_params_copied->size,
952                                                  sizeof(__u32))) {
953                                 retval = -EFAULT;
954                                 goto free_mem;
955                         }
956
957                 }
958 free_mem:
959                 kfree(algo_params_copied->params);
960                 kfree(algo_params_copied);
961                 break;
962         }
963         return retval;
964 }
965
966
967 int sst_ioctl_tuning_params(unsigned long arg)
968 {
969         struct snd_sst_tuning_params params;
970         struct ipc_post *msg;
971
972         if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
973                 return -EFAULT;
974         if (params.size > SST_MAILBOX_SIZE)
975                 return -ENOMEM;
976         pr_debug("Parameter %d, Stream %d, Size %d\n", params.type,
977                         params.str_id, params.size);
978         if (sst_create_large_msg(&msg))
979                 return -ENOMEM;
980
981         sst_fill_header(&msg->header, IPC_IA_TUNING_PARAMS, 1, params.str_id);
982         msg->header.part.data = sizeof(u32) + sizeof(params) + params.size;
983         memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
984         memcpy(msg->mailbox_data + sizeof(u32), &params, sizeof(params));
985         if (copy_from_user(msg->mailbox_data + sizeof(params),
986                         (void __user *)(unsigned long)params.addr,
987                         params.size)) {
988                 kfree(msg->mailbox_data);
989                 kfree(msg);
990                 return -EFAULT;
991         }
992         return sst_send_algo_ipc(&msg);
993 }
994 /**
995  * intel_sst_ioctl - receives the device ioctl's
996  * @file_ptr:pointer to file
997  * @cmd:Ioctl cmd
998  * @arg:data
999  *
1000  * This function is called by OS when a user space component
1001  * sends an Ioctl to SST driver
1002  */
1003 long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
1004 {
1005         int retval = 0;
1006         struct ioctl_pvt_data *data = NULL;
1007         int str_id = 0, minor = 0;
1008
1009         data = file_ptr->private_data;
1010         if (data) {
1011                 minor = 0;
1012                 str_id = data->str_id;
1013         } else
1014                 minor = 1;
1015
1016         if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
1017                 return -EBUSY;
1018
1019         switch (_IOC_NR(cmd)) {
1020         case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
1021                 pr_debug("IOCTL_PAUSE received for %d!\n", str_id);
1022                 if (minor != STREAM_MODULE) {
1023                         retval = -EBADRQC;
1024                         break;
1025                 }
1026                 retval = sst_pause_stream(str_id);
1027                 break;
1028
1029         case _IOC_NR(SNDRV_SST_STREAM_RESUME):
1030                 pr_debug("SNDRV_SST_IOCTL_RESUME received!\n");
1031                 if (minor != STREAM_MODULE) {
1032                         retval = -EBADRQC;
1033                         break;
1034                 }
1035                 retval = sst_resume_stream(str_id);
1036                 break;
1037
1038         case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
1039                 struct snd_sst_params str_param;
1040
1041                 pr_debug("IOCTL_SET_PARAMS received!\n");
1042                 if (minor != STREAM_MODULE) {
1043                         retval = -EBADRQC;
1044                         break;
1045                 }
1046
1047                 if (copy_from_user(&str_param, (void __user *)arg,
1048                                 sizeof(str_param))) {
1049                         retval = -EFAULT;
1050                         break;
1051                 }
1052
1053                 if (!str_id) {
1054
1055                         retval = sst_get_stream(&str_param);
1056                         if (retval > 0) {
1057                                 struct stream_info *str_info;
1058                                 char __user *dest;
1059
1060                                 sst_drv_ctx->stream_cnt++;
1061                                 data->str_id = retval;
1062                                 str_info = &sst_drv_ctx->streams[retval];
1063                                 str_info->src = SST_DRV;
1064                                 dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
1065                                 retval = copy_to_user(dest, &retval, sizeof(__u32));
1066                                 if (retval)
1067                                         retval = -EFAULT;
1068                         } else {
1069                                 if (retval == -SST_ERR_INVALID_PARAMS)
1070                                         retval = -EINVAL;
1071                         }
1072                 } else {
1073                         pr_debug("SET_STREAM_PARAMS received!\n");
1074                         /* allocated set params only */
1075                         retval = sst_set_stream_param(str_id, &str_param);
1076                         /* Block the call for reply */
1077                         if (!retval) {
1078                                 int sfreq = 0, word_size = 0, num_channel = 0;
1079                                 sfreq = str_param.sparams.uc.pcm_params.sfreq;
1080                                 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
1081                                 num_channel = str_param.sparams.uc.pcm_params.num_chan;
1082                                 if (str_param.ops == STREAM_OPS_CAPTURE) {
1083                                         sst_drv_ctx->scard_ops->\
1084                                         set_pcm_audio_params(sfreq,
1085                                                 word_size, num_channel);
1086                                 }
1087                         }
1088                 }
1089                 break;
1090         }
1091         case _IOC_NR(SNDRV_SST_SET_VOL): {
1092                 struct snd_sst_vol set_vol;
1093
1094                 if (copy_from_user(&set_vol, (void __user *)arg,
1095                                 sizeof(set_vol))) {
1096                         pr_debug("copy failed\n");
1097                         retval = -EFAULT;
1098                         break;
1099                 }
1100                 pr_debug("SET_VOLUME received for %d!\n",
1101                                 set_vol.stream_id);
1102                 if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
1103                         pr_debug("invalid operation!\n");
1104                         retval = -EPERM;
1105                         break;
1106                 }
1107                 retval = sst_set_vol(&set_vol);
1108                 break;
1109         }
1110         case _IOC_NR(SNDRV_SST_GET_VOL): {
1111                 struct snd_sst_vol get_vol;
1112
1113                 if (copy_from_user(&get_vol, (void __user *)arg,
1114                                 sizeof(get_vol))) {
1115                         retval = -EFAULT;
1116                         break;
1117                 }
1118                 pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n",
1119                                 get_vol.stream_id);
1120                 if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
1121                         pr_debug("invalid operation!\n");
1122                         retval = -EPERM;
1123                         break;
1124                 }
1125                 retval = sst_get_vol(&get_vol);
1126                 if (retval) {
1127                         retval = -EIO;
1128                         break;
1129                 }
1130                 pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
1131                                 get_vol.stream_id, get_vol.volume,
1132                                 get_vol.ramp_duration, get_vol.ramp_type);
1133                 if (copy_to_user((struct snd_sst_vol __user *)arg,
1134                                 &get_vol, sizeof(get_vol))) {
1135                         retval = -EFAULT;
1136                         break;
1137                 }
1138                 /*sst_print_get_vol_info(str_id, &get_vol);*/
1139                 break;
1140         }
1141
1142         case _IOC_NR(SNDRV_SST_MUTE): {
1143                 struct snd_sst_mute set_mute;
1144
1145                 if (copy_from_user(&set_mute, (void __user *)arg,
1146                                 sizeof(set_mute))) {
1147                         retval = -EFAULT;
1148                         break;
1149                 }
1150                 pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n",
1151                         set_mute.stream_id);
1152                 if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
1153                         retval = -EPERM;
1154                         break;
1155                 }
1156                 retval = sst_set_mute(&set_mute);
1157                 break;
1158         }
1159         case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
1160                 struct snd_sst_get_stream_params get_params;
1161
1162                 pr_debug("IOCTL_GET_PARAMS received!\n");
1163                 if (minor != 0) {
1164                         retval = -EBADRQC;
1165                         break;
1166                 }
1167
1168                 retval = sst_get_stream_params(str_id, &get_params);
1169                 if (retval) {
1170                         retval = -EIO;
1171                         break;
1172                 }
1173                 if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
1174                                         &get_params, sizeof(get_params))) {
1175                         retval = -EFAULT;
1176                         break;
1177                 }
1178                 sst_print_stream_params(&get_params);
1179                 break;
1180         }
1181
1182         case _IOC_NR(SNDRV_SST_MMAP_PLAY):
1183         case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
1184                 struct snd_sst_mmap_buffs mmap_buf;
1185
1186                 pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n");
1187                 if (minor != STREAM_MODULE) {
1188                         retval = -EBADRQC;
1189                         break;
1190                 }
1191                 if (copy_from_user(&mmap_buf, (void __user *)arg,
1192                                 sizeof(mmap_buf))) {
1193                         retval = -EFAULT;
1194                         break;
1195                 }
1196                 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
1197                 break;
1198         }
1199         case _IOC_NR(SNDRV_SST_STREAM_DROP):
1200                 pr_debug("SNDRV_SST_IOCTL_DROP received!\n");
1201                 if (minor != STREAM_MODULE) {
1202                         retval = -EINVAL;
1203                         break;
1204                 }
1205                 retval = sst_drop_stream(str_id);
1206                 break;
1207
1208         case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
1209                 struct snd_sst_tstamp tstamp = {0};
1210                 unsigned long long time, freq, mod;
1211
1212                 pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n");
1213                 if (minor != STREAM_MODULE) {
1214                         retval = -EBADRQC;
1215                         break;
1216                 }
1217                 memcpy_fromio(&tstamp,
1218                         sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1219                         sizeof(tstamp));
1220                 time = tstamp.samples_rendered;
1221                 freq = (unsigned long long) tstamp.sampling_frequency;
1222                 time = time * 1000; /* converting it to ms */
1223                 mod = do_div(time, freq);
1224                 if (copy_to_user((void __user *)arg, &time,
1225                                 sizeof(unsigned long long)))
1226                         retval = -EFAULT;
1227                 break;
1228         }
1229
1230         case _IOC_NR(SNDRV_SST_STREAM_START):{
1231                 struct stream_info *stream;
1232
1233                 pr_debug("SNDRV_SST_STREAM_START received!\n");
1234                 if (minor != STREAM_MODULE) {
1235                         retval = -EINVAL;
1236                         break;
1237                 }
1238                 retval = sst_validate_strid(str_id);
1239                 if (retval)
1240                         break;
1241                 stream = &sst_drv_ctx->streams[str_id];
1242                 mutex_lock(&stream->lock);
1243                 if (stream->status == STREAM_INIT &&
1244                         stream->need_draining != true) {
1245                         stream->prev = stream->status;
1246                         stream->status = STREAM_RUNNING;
1247                         if (stream->ops == STREAM_OPS_PLAYBACK ||
1248                                 stream->ops == STREAM_OPS_PLAYBACK_DRM) {
1249                                 retval = sst_play_frame(str_id);
1250                         } else if (stream->ops == STREAM_OPS_CAPTURE)
1251                                 retval = sst_capture_frame(str_id);
1252                         else {
1253                                 retval = -EINVAL;
1254                                 mutex_unlock(&stream->lock);
1255                                 break;
1256                         }
1257                         if (retval < 0) {
1258                                 stream->status = STREAM_INIT;
1259                                 mutex_unlock(&stream->lock);
1260                                 break;
1261                         }
1262                 } else {
1263                         retval = -EINVAL;
1264                 }
1265                 mutex_unlock(&stream->lock);
1266                 break;
1267         }
1268
1269         case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1270                 struct snd_sst_target_device target_device;
1271
1272                 pr_debug("SET_TARGET_DEVICE received!\n");
1273                 if (copy_from_user(&target_device, (void __user *)arg,
1274                                 sizeof(target_device))) {
1275                         retval = -EFAULT;
1276                         break;
1277                 }
1278                 if (minor != AM_MODULE) {
1279                         retval = -EBADRQC;
1280                         break;
1281                 }
1282                 retval = sst_target_device_select(&target_device);
1283                 break;
1284         }
1285
1286         case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1287                 struct snd_sst_driver_info info;
1288
1289                 pr_debug("SNDRV_SST_DRIVER_INFO received\n");
1290                 info.version = SST_VERSION_NUM;
1291                 /* hard coding, shud get sumhow later */
1292                 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1293                                                 sst_drv_ctx->encoded_cnt;
1294                 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1295                 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1296                 info.max_enc_streams = MAX_ENC_STREAM;
1297                 info.buf_per_stream = sst_drv_ctx->mmap_len;
1298                 if (copy_to_user((void __user *)arg, &info,
1299                                 sizeof(info)))
1300                         retval = -EFAULT;
1301                 break;
1302         }
1303
1304         case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
1305                 struct snd_sst_dbufs param;
1306                 struct snd_sst_dbufs dbufs_local;
1307                 struct snd_sst_buffs ibufs, obufs;
1308                 struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
1309                 char __user *dest;
1310
1311                 pr_debug("SNDRV_SST_STREAM_DECODE received\n");
1312                 if (minor != STREAM_MODULE) {
1313                         retval = -EBADRQC;
1314                         break;
1315                 }
1316                 if (copy_from_user(&param, (void __user *)arg,
1317                                 sizeof(param))) {
1318                         retval = -EFAULT;
1319                         break;
1320                 }
1321
1322                 dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
1323                 dbufs_local.output_bytes_produced =
1324                                         param.output_bytes_produced;
1325
1326                 if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
1327                         retval = -EFAULT;
1328                         break;
1329                 }
1330                 if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
1331                         retval = -EFAULT;
1332                         break;
1333                 }
1334
1335                 ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
1336                 obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
1337                 if (!ibuf_tmp || !obuf_tmp) {
1338                         retval = -ENOMEM;
1339                         goto free_iobufs;
1340                 }
1341
1342                 if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
1343                                 ibufs.entries * sizeof(*ibuf_tmp))) {
1344                         retval = -EFAULT;
1345                         goto free_iobufs;
1346                 }
1347                 ibufs.buff_entry = ibuf_tmp;
1348                 dbufs_local.ibufs = &ibufs;
1349
1350                 if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
1351                                 obufs.entries * sizeof(*obuf_tmp))) {
1352                         retval = -EFAULT;
1353                         goto free_iobufs;
1354                 }
1355                 obufs.buff_entry = obuf_tmp;
1356                 dbufs_local.obufs = &obufs;
1357
1358                 retval = sst_decode(str_id, &dbufs_local);
1359                 if (retval) {
1360                         retval = -EAGAIN;
1361                         goto free_iobufs;
1362                 }
1363
1364                 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1365                 if (copy_to_user(dest,
1366                                 &dbufs_local.input_bytes_consumed,
1367                                 sizeof(unsigned long long))) {
1368                         retval = -EFAULT;
1369                         goto free_iobufs;
1370                 }
1371
1372                 dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
1373                 if (copy_to_user(dest,
1374                                 &dbufs_local.output_bytes_produced,
1375                                 sizeof(unsigned long long))) {
1376                         retval = -EFAULT;
1377                         goto free_iobufs;
1378                 }
1379 free_iobufs:
1380                 kfree(ibuf_tmp);
1381                 kfree(obuf_tmp);
1382                 break;
1383         }
1384
1385         case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
1386                 pr_debug("SNDRV_SST_STREAM_DRAIN received\n");
1387                 if (minor != STREAM_MODULE) {
1388                         retval = -EINVAL;
1389                         break;
1390                 }
1391                 retval = sst_drain_stream(str_id);
1392                 break;
1393
1394         case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
1395                 unsigned long long __user *bytes = (unsigned long long __user *)arg;
1396                 struct snd_sst_tstamp tstamp = {0};
1397
1398                 pr_debug("STREAM_BYTES_DECODED received!\n");
1399                 if (minor != STREAM_MODULE) {
1400                         retval = -EINVAL;
1401                         break;
1402                 }
1403                 memcpy_fromio(&tstamp,
1404                         sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
1405                         sizeof(tstamp));
1406                 if (copy_to_user(bytes, &tstamp.bytes_processed,
1407                                 sizeof(*bytes)))
1408                         retval = -EFAULT;
1409                 break;
1410         }
1411         case _IOC_NR(SNDRV_SST_FW_INFO): {
1412                 struct snd_sst_fw_info *fw_info;
1413
1414                 pr_debug("SNDRV_SST_FW_INFO received\n");
1415
1416                 fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
1417                 if (!fw_info) {
1418                         retval = -ENOMEM;
1419                         break;
1420                 }
1421                 retval = sst_get_fw_info(fw_info);
1422                 if (retval) {
1423                         retval = -EIO;
1424                         kfree(fw_info);
1425                         break;
1426                 }
1427                 if (copy_to_user((struct snd_sst_dbufs __user *)arg,
1428                                 fw_info, sizeof(*fw_info))) {
1429                         kfree(fw_info);
1430                         retval = -EFAULT;
1431                         break;
1432                 }
1433                 /*sst_print_fw_info(fw_info);*/
1434                 kfree(fw_info);
1435                 break;
1436         }
1437         case _IOC_NR(SNDRV_SST_GET_ALGO):
1438         case _IOC_NR(SNDRV_SST_SET_ALGO):
1439                 if (minor != AM_MODULE) {
1440                         retval = -EBADRQC;
1441                         break;
1442                 }
1443                 retval = intel_sst_ioctl_dsp(cmd, arg);
1444                 break;
1445
1446         case _IOC_NR(SNDRV_SST_TUNING_PARAMS):
1447                 if (minor != AM_MODULE) {
1448                         retval = -EBADRQC;
1449                         break;
1450                 }
1451                 retval = sst_ioctl_tuning_params(arg);
1452                 break;
1453
1454         default:
1455                 retval = -EINVAL;
1456         }
1457         pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval);
1458         return retval;
1459 }
1460